OpenAPI Specification と Swagger Codegen に至るまで辿った道
ポエムです。コードが1行も出てこないので じっちゃん に怒られそうです。
Remote Procedure Call(RPC)に長年興味を持ち、実案件で使ってきました。
RPC は、ネットワーク上にあるロジックを関数呼び出しで実行することができ、通信のためのコードを隠蔽する技術と考えています。
RPCに関し、OpenAPI Specification(Swagger Codegen)に辿り着くまでの道を振り返ってみました。
CORBA
- Common Object Request Broker Architecture
- 様々なプログラミング言語で書かれたソフトウェアコンポーネントの相互利用を可能にするもの(分散オブジェクト技術)
- サポートされる異言語間の通信が可能
- IIOP というプロトコルを使っている
CORBA の歴史は長いみたいですが、私が実案件で使ったのは今世紀に入ってからだったと思います。
「分散オブジェクト」という言葉の響きで中二心を揺さぶられました。
VisiBroker, Orbix といった実装を使っていましたが、もうすっかり忘れてしまいました。
IDL(インターフェース記述言語)、スタブ、スケルトンという言葉をこの時、知りました。
IDL を書いて、クライアントのスタブ、サーバのスケルトンのコードを自動生成するアプローチですね。
そして今、CORBA が息をしているかも知りません。
RMI
- Remote Method Invocation
- Javaで書かれたプログラム間のORB(オブジェクトリクエストブローカー)であり、RPCのオブジェクトに相当する機能を果たすためのJavaアプリケーションプログラミングインタフェース。
RMI も実案件で使いました。
Java 限定なので IDL も不要でシンプルだと思いました。
Java5 の頃に利用し今でも気に入っています。
デメリットとしては、サーバ側に変更が入ると、クライアント側も同じタイミングでデプロイしないといけないということでしょうか?
頻繁に変更することがなかったためか、それで困ったことはなかったです。
SOAP
CORBA の HTTP 版みたいな感じで、Firewall を超えやすいといったところでしょうか。
実案件で使ったのはクライアント側だけです。
SOAP は今でもちょっと使われている感があります。
Thrift
CORBA を今風に改良した感じでしょうか。
実案件でクライアント側を使ってきました。
Javaクライアントを開発してたはずなのに、デカめの Scala のランタイム jar が Maven レポジトリから降臨してきた時に、ナヌーって声に出してしまいました(Thiriftじゃなくfinagleの依存だったかな)。
gRPC
Google が作った オレオレ CORBA といったところでしょうか。
最近 1.0 になったばかり。
Thrift の後発で競合しそうです。
HTTP2 ベースということで、Android や iOS からの利用も期待できそうです。
実案件では使っていません。
ちょっと試したところ、Java サーバアプリのビルドで、C++ のコンパイラが必要になりちょっと萎えました。
でだ
RPC というアプローチはインターフェースをちゃんと定義し良いと思うんですが、なかなか周りに受け入れらる感触がないです。
なんか難しそうという印象を与えてしまう。
クライアント(利用者)側から依存ライブラリ増やしたくないんだよと言われる。
REST
みんな大好き REST !
バズワード的に広まったマイクロサービスもデフォルトが REST とされています。
私は、REST より SOAP だろうと思ってた人です。
REST は インターフェース定義が不明確。
クライアントが Web ブラウザなら良いと思うけど。。
みんな、おのおのに同じようなクライアントのコードを書いて楽しい?疲れない?
嘘だらけのAPI仕様ドキュメント
じゃあ逆に、REST を RPC の方に寄せられないだろうかと思うようになりました。
明確にインターフェースを定義できれば RPC 的な事が実現できるはず。。
WADL
そもそも REST における WSDL みたいなインターフェース定義みたいなのないの?と思っていたところ、WADLを発見しました。
- Web Application Description Language
- World Wide Web Consortium (W3C) により提案
- XML で REST の Interface を定義
しかーし、この存在知ってる人あまりいないですよね !
そして、2015年、、
Open API Initiative
(゚∀゚)キタコレ!!
でも やってる事 WADL とかぶってないか。
OpenAPI Specification(Swagger)
で、 Open API Initiative が推進する OpenAPI Specification です。
もともと Swagger というフレームワークがあり、それをベースにしています。
XML ではなく今風に YAML, JSON でインターフェースを定義します。
Swagger Editor でインターフェースを定義することができます。
http://editor.swagger.io/editor.swagger.io
Swagger のメリットは、二つあると思います。
一つは、インターフェースを定義することにより、ドキュメントの自動生成や Swagger UI により インターラクティヴな実際に REST クライアントとして動くドキュメントを生成できます。
以下は、Swagger UI の例です。
http://petstore.swagger.io
もう一つのメリットは、RPC を実現する Swagger Codegen です。
インターフェース定義からサーバ・クライアントのコードを自動生成します。様々な言語・フレームワークのコードを生成できます。
また生成されるコードが気に入らない場合は、自分でカスタマイズできます。
下記は、対応する言語・フレームワークです。
Client
- ActionScript
- C++
- C#
- Clojure
- Dart
- Groovy
- Go
- Java
- Java
- NodeJS/Javascript
- Objective-C
- Perl
- PHP
- Python
- Ruby
- Scala
- Swift
- TypeScript (Node)
- TypeScript (Angular1)
- TypeScript (Angular2)
- TypeScript (Fetch)
Server
- C# ASP.NET5
- C# NancyFX
- Erlang Server
- Go Server
- Haskell Servant
- Java MSF4J
- Java Spring Boot
- Java Undertow
- Java Play Framework
- JAX-RS RestEasy
- JAX-RS CXF
- JAX-RS CXF (CDI)
- JAX-RS RestEasy (JBoss EAP)
- PHP Lumen
- PHP Slim
- PHP Zend Expressive (with Path Handler)
- Ruby on Rails 5
- Scala Finch
デメリットとしてコード生成系のプロダクトはどうしてもバグが入りやすくなる感じで、プロダクトに対して利用者がコントリビュートしていかなければいけないところだとは思います。
SpringFox
実際、私は Swagger をどう利用しているかといいますと、インターフェス定義を直に書いていません。
Java の Spring MVC と SpringFox というライブラリを利用することにより、サーバアプリからインターフェース定義を自動生成しています。
そのインターフェース定義からクライアントのコードを自動生成して提供しています。
SpringFox の一つの不安は、Spring の中の人は、たぶん Swagger に関心がないのでは?というところ。
Spring REST Docs というドキュメントだけ生成する仕組みを別に持っています。
Swagger のように実装コードにドキュメンテーション用のコードが入ることを嫌い、それはテストコード側にあった方が良いという考えだと思います。
個人的には、Spring に SpringFox 自体を取り込んでも良いのでは?と思うところですが。
Sinatra にインスパイアされた系のフレームワークより、 Spring MVC みたいなリフレクションベースのフレームワークの方が、Swagger と相性が良いんですよね。
Spring MVC はメソッドのシグネチャ見れば、RESTの仕様も分かっちゃうんで。
SpringFox のデメリットは、アプリサイズが大きくなることです。SpringFox が guava に依存していて、そのサイズが2.2Mあるのです。guava依存外せないものかなー。
ここのスライドでは、31MB と書いてあるんですが、ランタイムでそんなに増えることは決してありません。これを見て SpringFox 使うの諦めた人がいるかも。。
Swagger で Web バックエンドと Web フロントエンドをタイプセーフにつなぐ
以前に書いた記事ですが、TypeScript のコードを生成することにより、Web バックエンドと Web フロントエンドがタイプセーフに繋がります。
まとめ
OpenAPI Specification(Swagger) は、クライアント側に二つの選択肢を与えます。
RPC なんて嫌だという人は、 Swagger UI を見てクライアントのコードを実装できます。
タイプセーフにしたいから RPC が良いという人は、 Swagger Codegen でクライアントのコードを得る事ができます。
RPC的なアプローチをクライアント側に対して押しつける必要もありません。
クライアント側は自由です。
妥協点というか、落とし所を見つけた感じであります。はい。
(記事の中でマイクロサービスやらSOAとかの言葉を使った方が釣りやすいと思ったけど止めた)
以上
マイクロサービスアーキテクチャ [ SamNewman ] |