Squareの内部APIの仕組み

http://corner.squareup.com/2014/09/squares-api.html

1 comment | 2 points | by WazanovaNews 2年以上前 edited


Jshiike 2年以上前 edited | ▲upvoteする | link

SOAにおけるサービス間のコミュニケーションについては、CODE CLIMATEにおいて、Protocol Buffers vs JSONという比較が取り上げられていて、「ブラウザやJavaScriptが直接データを利用しないケース、特に内部サービス間のコミュニケーションにはProtocol Buffersの方が向いているのでは。」と紹介されています。

  • せっかく整合性のあるデータ構造を用意しても、サービス間のデータのやり取りの際に苦労させられることが多い。Protocol BuffersならProtoフォーマットにしてエンコーディングするだけで、意図するビジネスルールを維持できる。
  • 番号のフィールドがあるので、バージョンのチェックが不要。後方互換性を担保するために、コードの振る舞いを変更するような事態を避けられる。
  • 例えば、RubyとJSONのエンコード/デコードでは、お手製の定型雛形構文をつくるハメになる。Parser/Presenterクラスにも密かにビジネスロジックが含まれことも多く、まるで手動でパースするような作業の危険度が上がる。一方、Protocol Buffersはスタブクラスを生成し、ほぼ同じ目的を難なく実現できる。スキーマに修正が入っても、protoがクラスに反映をしてくれるので、開発者はアプリづくりにもっと専念できる。
  • required/optional/repeatedなどを使って柔軟に定義し。安全にデータをおくれる。RiakのようなDBシステムがProtocol Buffersを利用してるので、そのインターフェースを確認するとニュアンスが掴めると思う。例えば、Ruby Protocol Buffersライブラリを利用すると、必要なフィールドに値が入ってないオブジェクトインスタンスをエンコードする際、exceptionをだしてくれる。
  • フィールドやデータ型をJSONのエンコード/デコードスキーマで都度調整するよりも、複数の言語/フレームワークでつくられたサービス間のコミュニケーションをスムーズに段取ってくれる。

JSONを使うべきなのは、

  • データの可読性が重要。
  • データがウェブブラウザで直接利用される。
  • サーバサイドのアプリがJavaScriptで書かれている。
  • データモデルとスキーマがまだ紐づいていない。
  • 新しいツールを覚える時間、もしくは新たなネットワークサービスを運営する工数がない。

というケースだとしています。

それに対しては、下記のような反対意見もありました。

  • JSONでスキーマを実装できないわけではなく、実際には暗黙的でもやっているケースが多い。
  • JSONにバージョンがなくても、適宜フィールドを追加/削除すればよいだけのこと。
  • フロント側で全ての型チェック、フィールドチェックをしたいということであればわかるが、厳密にしようとして、”get attribute” exceptionが連発されると、質の悪いデータ構造ではないかと疑いたくなる。Python/Ruby/JavaScriptで書く際は、厳密なデータ構造や定型雛形構文をまず第一に避けることを念頭に置いている。
  • タイプセーフな言語では、JSONライブラリでデータ構造を事前に定義できるケースも多く、定型雛形構文を書くような追加作業は少ない。
  • JSONでも複数言語対応に難はない。
  • Python/Ruby/JavaScriptのような動的型付き言語でProtocol Buffersを採用する論拠は弱いのではないか。
  • Spotifyでは、逆にProtocol BuffersからJSONに移行中。JSONの、幅広くサポート / シンプルなパースの仕組み / 開発者が扱いやすい / デバッグ & モックがしやすいなどの点が、Protocol Buffersのメリットを上回るから。

さて今回Squareでは、Protocol Buffersをベースに適宜JSONに翻訳するというアプローチをとっています。

  • 複数の言語/フレームワークで構築したSOAシステムにおいて、内部のAPIは一部のレガシーシステムを除いて原則Protocol Buffersを採用。

  • Ruby/JavaScriot/Go/Objective C/Python/Javaと多岐に渡るので、APIを利用する開発者が実装の詳細に関わらなくて済むようにした。Protocol Buffersだと常にドキュメントと整合性のとれた定義が実行できる。

  • 実は、まずProtocol Buffersで定義し、それからHTTP JSON APIに翻訳した。大変に聞こえるかもしれないが、実装との分離性を高めたかたちで、APIをよく吟味して、かつ慣習をうまく取り込んで、整合性のとれたものを用意するにはよい方法だった。全体コストの削減ができた。

  • GoやJavaのようなタイプセーフの言語では、JSONのAPIは辛い。多相性のデータ構造と動的なキーでAPIを書くのが難しい。作業コストがAPIを利用するメリットを上回ってしまう危険性がある。

  • 200を超えるサービスを扱うNode.jsサーバのために、Protocol BuffersのライブラリProtobを開発した。Protocol Buffersの公式パーサであるProtocを利用し、JSONをアウトプットする。ランタイム時にこのJSONを読込み、メッセージ / サービス / enumのconstructorを生成する。

  • 定義のドキュメントを抽出して、見やすいかたちにまとめてくれるシングルページアプリPilgrimも用意した。PilgrimがSquare APIの情報をまとめたサンプルはこちらで確認できる。大量のAPIを簡単に閲覧でき、google.protobuf.FieldOptionsのようなprotoのextensionの確認もできる。

ProtobPilgrimはオープンソースとして提供されています。

#sqaure #api #protocolbuffers #json #soa


ワザノバTop200アクセスランキング


Back