テクノブログ:EvernoteがAPIを構築するためにApache Thriftを選んだ理由

rif約

2007年にEvernoteサービスの配置を計画し始めたとき、初日にはシン(ブラウザなど)とシック同期クライアントの両方のサポートが必要になることがわかりました。 このため、Web用のGUIで作業を開始する前に、リモートプロトコルとクライアントAPIについて考えるようになりました。 そうでなければ、APIが既存のWebサービスにねじ込まれるまで数ヶ月待たなければなりません。



当社のアプリケーションは、次のような特定の要件をAPIに課しています。

  1. クロスプラットフォーム。 2008年2月に開始したとき、サーバー側でJavaを使用し、クライアント側でWin32 C ++およびCocoa Objective-Cを使用した既製のコードがありました。
  2. コンパクトなデータ転送。 Evernoteクライアントアプリケーションはノートを同期します。ノートには、合計数十メガバイトの数百の埋め込み画像を含めることができます。 15メガバイトのメモを転送すると、正確にはこれらの15メガバイトの転送を意味するAPIが欲しいです。
  3. 前方/後方互換性。 ユーザーがコンピューターにクライアントのバージョンをインストールした後、データ構造のモデルを展開するたびにソフトウェアを更新するように強制したくありません。
  4. プログラミング言語へのバインド(バインド)。 各クライアントのデータ構造を解析およびシリアル化するための多くのコードを記述したくありませんでした。 これには多くの時間がかかり、エラーが発生します。また、実際には3番目のポイントは実行不可能です。
  5. 標準および/またはオープンソースに基づいています。 すべてが平等であるため、明白な理由により、当社のサービスのAPIを独自技術に関連付けたくありませんでした。
  6. コンパクト。 各モバイルクライアントにメガバイトのコードと200のクラスを追加しないことをお勧めします。


数か月かけて、さまざまな代替案の調査とテストを行いました。 XML-RPCまたはSOAPは要件の1つ( 1、5 )、 ZeroCのICE-もう1つ( 2、4 )を満たしました。 ある時点で、自転車を発明し、独自の小さなアドホックプロトコルを展開することさえ考えました。



私たちの友人の一人は、 Facebookで使用された最近開いたThriftフレームワークに注意を払うことを勧めました。 Facebookは、バックエンドサーバーでの内部作業でこれを使用して、他の内部サーバーとメッセージを交換しました。多くの場合、異なる言語(PHPやC ++など)でコードペアリングを処理する必要がありました。 そして、他の人は、私たちが知る限り、Thriftを同様のタスクに使用しました:内部バックエンドサーバーの通信を提供します。



私たちは、サーバーとサーバー間の通信だけでなく、インターネットを介した大規模なクライアントとサーバーの同期にも使用できるフレームワークを探していました。 同時に、Thriftはすべての要件に理想的に適合しました。

  1. クロスプラットフォーム。 Thriftのインターフェイス定義言語(Interface Definition Language)を使用して、データのモデルとサービスの操作を定義し、コンパイル後、出力で多数の異なる言語のクライアントコードとサーバーコードを取得します。
  2. コンパクトなデータ転送。 構造の説明でbianarフィールドがあることを示し、そこに1メガバイトのデータを入れると、結果として、この1メガバイトが通信チャネルを介して送信されます。
  3. 前方/後方互換性。 これは、Thriftが本当に比類のない場所です。 Thriftがどのように機能するかをある程度正確に理解していれば(もちろん、すぐに提供されるとは限りません)、既存のクライアントに違反することなく、構造、フィールド、ユーティリティメソッド、関数パラメーターを追加できます。 3年前にリリースされたWindowsまたはMacのクライアントは、現在はEvernoteと同期できます。
  4. プログラミング言語へのバインド(バインド)。 ポイント1を参照してください。最初は、ThriftでObjective-C Cocoaのサポートがなかったため、Andrew McGeachie(Macクライアントを開発するための「人間チーム」)がThriftコンパイラにこのサポートを追加しました。
  5. 標準および/またはオープンソースに基づいています。 FacebookはThriftの開発をApache Software Foundationに移管しました。
  6. コンパクト。 Thrift実行可能ライブラリと生成されたコードは、非常に小さく理解しやすいことが判明しました。 彼らは何をしているのかを簡単に読んで理解することができます(ただし、追加のコードで大きくなりすぎていますが、今日でも、これは代替手段に比べて最もコンパクトなオプションです)。


最終的に、 EvernoteサービスAPIを取得しました。これは、生成されたネイティブコードを使用して、すべての顧客(および数百のアフィリエイトアプリケーション )に共通のAPIを介した対話を提供します。 多くの場合、複数のプラットフォームでEvernoteを使用している300万人以上のアクティブユーザーにより、Thriftを使用するほとんどのコンピューター/デバイスにはEvernoteクライアントが搭載されているように思えます。



あなたはどうですか?



Webサービス用のAPIを実装しようとしています。 Thriftを使用する必要がありますか?



アプリケーションの要件がEvernoteとまったく同じである場合、Thriftが適切な選択である可能性があります。 大きなバイナリ構造を持つ複雑なデータモデルに出会わない場合(セクション2)、答えはそれほど明白ではありません。



より単純なデータモデルを使用するWebサービスは、通常、XMLまたはJSONを介したデータシリアル化を使用した、あまり洗練されていないRESTプロトコルを使用します。 このアプローチにより、単純な操作のテストと実行が非常に簡単になります。 Twitter APIを使用していくつかのことを行う必要がある場合は、curl / wgetを使用してコマンドラインから手動でテストし、printf / println / regexpsなどを使用してコードをアプリケーションにねじ込むことができます。非常に低いこのタイプのAPIの使用を開始してください。



Thrift APIは、完全にテストを開始する前に、アプリケーション内のライブラリのトランスファー層と相互依存性のすべての詳細に対処する必要がある開発者により高い要件を設定します。 APIを使用してさまざまな言語のコード例を提供していますが、それでも単純なRESTスキームを使用するよりも時間がかかるタスクです。



一方、これらのタイプのAPIに対する低い障壁は、原則として、型指定されていないデータのシリアル化を単純化し、その後の互換性の問題を引き起こします(セクション3)。 Twitterゲートウェイは、独立したTwitter4Jライブラリを使用して、RESTベースのTwitter APIと対話します。 昨年、Twitterのサーバー側の変更と、それに続くTwitter4JのXMLデータ構造の誤った解釈(たとえば、ツイートIDのビット長)により、ゲートウェイが少なくとも数回壊れました。



より正式なIDLおよびネイティブコード生成により、長期的に安定したクライアント作業が保証されるため、開発者向けのThriftの初期の複雑さは、作成者がクライアントコードの安定性と長寿命に関心がある一部のサービスで補うことができます。



All Articles