web-dev-qa-db-ja.com

Apache Thrift、Google Protocol Buffers、MessagePack、ASN.1、Apache Avroの主な違いは何ですか?

これらはすべて、バイナリシリアル化、RPCフレームワーク、およびIDLを提供します。それらと特性(パフォーマンス、使いやすさ、プログラミング言語のサポート)の重要な違いに興味があります。

他の同様の技術を知っている場合は、回答でそれを言及してください。

121
andreypopp

ASN.1はISO/ISE標準です。非常に読みやすいソース言語と、バイナリおよび人間が読めるさまざまなバックエンドを備えています。国際標準である(そしてそれは古いものです!)ソース言語は、少しキッチンに似ています(大西洋が少し濡れているのとほぼ同じ方法で)が、非常によく指定されており、十分なサポートがあります。 (恐らく十分に掘り進めれば、名前を付けた言語のASN.1ライブラリを見つけることができ、そうでなければ、FFIで使用できる優れたC言語ライブラリが利用可能です。)それは、標準化された言語であり、いくつかの優れたチュートリアルも利用できます。

Thriftは標準ではありません。もともとはFacebookのもので、後にオープンソース化され、現在はトップレベルのApacheプロジェクトです。それは十分に文書化されていません-特にチュートリアルレベル-そして、私の(確かに短い)一見では、他の、以前の努力がまだしていない(そして場合によってはより良い)何かを追加するようには見えません。それを公平にするために、それはいくつかのより有名な非主流の言語を含む、箱から出してサポートするかなり多くの言語を持っています。 IDLも漠然とCに似ています。

プロトコルバッファは標準ではありません。これは、より広範なコミュニティにリリースされているGoogle製品です。箱から出してサポートされる言語に関しては少し制限されています(C++、PythonおよびJava)のみをサポートしています)が、他の言語(多くのGoogleはプロトコルバッファを使用してほとんどすべての作業を行っているため、バトルテスト済みのバトル強化プロトコルです(ただし、ASN.1ほどのバトル強化ではありません。Thriftよりも優れたドキュメントがありますが、しかし、Googleの製品であるため、不安定になる可能性が非常に高くなります(常に変化するという意味で、信頼性が低いという意味ではありません)。IDLもCに似ています。

上記のシステムはすべて、ある種のIDLで定義されたスキーマを使用して、ターゲット言語のコードを生成し、エンコードおよびデコードで使用します。 Avroはしません。 Avroのタイピングは動的であり、そのスキーマデータは、実行時にエンコードとデコードの両方に直接使用されます(処理には明らかなコストがありますが、動的言語やタイプにタグ付けする必要がないなどの明らかな利点もあります) 。そのスキーマはJSONを使用しているため、JSONライブラリが既にある場合は、新しい言語でAvroをサポートするのが少し簡単になります。繰り返しになりますが、ほとんどのホイール再発明プロトコル記述システムと同様に、Avroも標準化されていません。

個人的には、それとの愛/憎しみの関係にもかかわらず、RPCスタックは実際にはありませんが、ほとんどのRPCおよびメッセージ送信の目的におそらくASN.1を使用します(1つを作成する必要がありますが、IOCはそれを作成します)簡単です)。

シリアライザーについて内部調査を行ったところです。ここにいくつかの結果を示します(今後の参考のために!)

節約=シリアル化+ RPCスタック

最大の違いは、Thriftは単なるシリアル化プロトコルではなく、現代のSOAPスタックのような完全なRPCスタックです。したがって、シリアル化の後、オブジェクトcould(ただし必須ではありません)TCP/IPを介してマシン間で送信されます。SOAPでは、利用可能なものを完全に記述するWSDLドキュメントから始めましたサービス(リモートメソッド)および予想される引数/オブジェクト。これらのオブジェクトはXMLを介して送信されます。Thriftでは、.thriftファイルは利用可能なメソッド、予想されるパラメータオブジェクトを完全に記述し、オブジェクトは利用可能なシリアライザの1つ(Compact Protocolは、効率的なバイナリプロトコルであり、本番環境で最も普及しています。

ASN.1 =グランドパパ

ASN.1は80年代の通信関係者によって設計され、CompSciの人々から登場した最近のシリアライザーと比較して、ライブラリサポートが限られているため、awkwardを使用します。 DER(バイナリ)エンコーディングとPEM(ascii)エンコーディングの2つのバリアントがあります。どちらも高速ですが、DERは2つの方が高速でサイズ効率が高くなります。実際、ASN.1 DERは、それ自身が設計された30年後に設計されたシリアライザーを簡単に維持することができます(時にはビートすることもあります)。非常にコンパクトで、Protocol BuffersおよびThriftよりも小さく、Avroのみに負けています。問題は、サポートする優れたライブラリがあることであり、現時点ではBouncy CastleがC#/ Javaに最適なライブラリのようです。 ASN.1はセキュリティおよび暗号化システムの王様であり、消えることはありません。そのため、「将来の校正」について心配する必要はありません。良いライブラリを入手してください...

MessagePack =パックの中央

悪くはありませんが、最速でも、最小でも、最高のサポートでもありません。それを選択する生産上の理由はありません。

一般

それ以外は、かなり似ています。ほとんどは、基本的なTLV: Type-Length-Value原則。

プロトコルバッファ(Googleが発信)、Avro(Apacheベース、Hadoopで使用)、Thrift(Facebookが発信、現在はApacheプロジェクト)およびASN.1(Telecomが発信)はすべて、シリアライザで最初にデータを表現するコード生成のレベルを伴います固有の形式の場合、シリアライザー「コンパイラー」は、code-gen 段階。アプリのソースはこれらのcode-gen IOのクラス。特定の実装(例:MicrosoftのAvroライブラリまたはMarc GavelのProtoBuf.NET)を使用すると、アプリレベルのPOCO/POJOオブジェクトを直接装飾でき、ライブラリはコード生成クラスではなく、これらの装飾クラスを直接使用します。これにより、オブジェクトコピーステージ(アプリケーションレベルのPOCO/POJOフィールドからcode-genフィールドまで)が不要になるため、パフォーマンスが向上することがわかりました。

いくつかの結果と一緒に遊ぶライブプロジェクト

このプロジェクト( https://github.com/sidshetye/SerializersCompare )は、C#の世界で重要なシリアライザーを比較します。 Java人々は既に 類似したもの を持っています。

1000 iterations per serializer, average times listed
Sorting result by size
Name                Bytes  Time (ms)
------------------------------------
Avro (cheating)       133     0.0142
Avro                  133     0.0568
Avro MSFT             141     0.0051
Thrift (cheating)     148     0.0069
Thrift                148     0.1470
ProtoBuf              155     0.0077
MessagePack           230     0.0296
ServiceStackJSV       258     0.0159
Json.NET BSON         286     0.0381
ServiceStackJson      290     0.0164
Json.NET              290     0.0333
XmlSerializer         571     0.1025
Binary Formatter      748     0.0344

Options: (T)est, (R)esults, s(O)rt order, (S)erializer output, (D)eserializer output (in JSON form), (E)xit

Serialized via ASN.1 DER encoding to 148 bytes in 0.0674ms (hacked experiment!)
37
DeepSpace101

パフォーマンスの観点に加えて、Uberは最近、エンジニアリングブログでこれらのライブラリのいくつかを評価しました。

https://eng.uber.com/trip-data-squeeze/

彼らの勝者は? MessagePack +圧縮用のzlib

私たちの目標は、エンコードプロトコルと圧縮アルゴリズムの組み合わせを、最も高速で最もコンパクトな結果で見つけることでした。 Uber New York Cityからの2,219の擬似ランダム匿名化旅行でエンコードプロトコルと圧縮アルゴリズムの組み合わせをテストしました(JSONとしてテキストファイルに入力)。

ここでの教訓は、あなたの要件がどのライブラリがあなたにとって適切かを左右するということです。 Uberの場合、メッセージパッシングのスキーマレス性により、IDLベースのプロトコルを使用できませんでした。これにより、多数のオプションがなくなりました。また、彼らにとって重要なのは、生のエンコード/デコード時間だけでなく、保存されているデータのサイズです。

サイズ結果

Size Results

スピード結果

enter image description here

12
Avner

ASN.1の大きな特徴の1つは、istが仕様not実装用に設計されていることです。したがって、「実際の」プログラミング言語での実装の詳細を非表示/無視するのに非常に優れています。

Asn1-fileにエンコーディングルールを適用し、両方から実行可能コードを生成するASN.1-Compilerの仕事。エンコーディングルールは、EnCoding Notation(ECN)で提供されるか、BER/DER、PER、XER/EXERなどの標準化されたルールのいずれかです。つまり、ASN.1はタイプと構造であり、エンコーディングルールはワイヤエンコーディングを定義し、最後に、コンパイラがプログラミング言語に転送します。

無料のコンパイラは、私の知る限り、C、C++、C#、Java、およびErlangをサポートしています。 (非常に高価で特許/ライセンスを所有している)商用コンパイラは非常に用途が広く、通常は絶対に最新であり、時にはさらに多くの言語をサポートしますが、サイト(OSS Nokalva、Marbenなど)を参照してください。

この手法を使用すると、まったく異なるプログラミング文化の当事者(たとえば、「組み込み」の人々と「サーバーファーマー」)の間のインターフェイスを指定するのは驚くほど簡単です。asn.1-file、エンコードルールなど。 BERおよびe.g. UML相互作用図。それがどのように実装されるか心配する必要はありません。誰もが「彼らのもの」を使用できるようにしましょう!私にとっては非常にうまく機能しています。 Btw .: OSS Nokalvaのサイトには、ASN.1に関する無料でダウンロードできる本が少なくとも2冊あります(1冊はLarmouth、もう1冊はDubuisson)。

私見の他の製品のほとんどは、まだ別のRPCスタブジェネレーターになろうとしているだけで、シリアル化の問題に大量の空気を送り込んでいます。まあ、それが必要なら、大丈夫かもしれません。しかし、私にとっては、それらはSun-RPCの再発明のように見えます(80年代後半から)が、ちょっと、それもうまくいきました。

11
njimko

MicrosoftのBond( https://github.com/Microsoft/bond )は、パフォーマンス、機能、およびドキュメントが非常に印象的です。ただし、現在(2015年2月13日)には多くのターゲットプラットフォームをサポートしていません。それは非常に新しいからだと推測できます。現在、python、c#、c ++をサポートしています。それはどこでもMSによって使用されています。 bond#を使用するc#開発者はprotobufを使用するよりも優れているため、試してみましたが、節約も使用しましたが、直面した唯一の問題はドキュメントに関するものでした。

Bondのリソースは次のとおりです( https://news.ycombinator.com/item?id=8866694https://news.ycombinator.com/item?id=8866848https://Microsoft.github.io/bond/why_bond.html

パフォーマンスのために、1つのデータポイントは jvm-serializers ベンチマーク-それは非常に具体的で小さなメッセージですが、Javaプラットフォームにいる場合に役立ちます。また、著者の言葉を福音として決して受け取らないでください;宣伝されている主張の多くは偽物です(たとえば、msgpackサイトには疑わしい主張があります;速いかもしれませんが、情報は非常に大雑把で、ユースケースはあまりありません現実的)。

大きな違いの1つは、スキーマを使用する必要があるかどうかです(少なくともPB、Thrift、Avroはオプションかもしれません; ASN.1私も思う; MsgPack、必ずしもそうではありません)。

また、私の意見では、階層化されたモジュラー設計を使用できるのは良いことです。つまり、RPCレイヤーはデータ形式、シリアル化を指示するべきではありません。残念ながら、ほとんどの候補者はこれらをしっかりとバンドルしています。

最後に、データ形式を選択するとき、今日のパフォーマンスはテキスト形式の使用を排除しません。非常に高速なJSONパーサー(および非常に高速なストリーミングxmlパーサー)があります。また、スクリプト言語からの相互運用性と使いやすさを考慮すると、バイナリ形式とプロトコルは最良の選択ではないかもしれません。

5
StaxMan