Was sind die Hauptunterschiede zwischen Apache Thrift, Google Protocol Buffers, MessagePack, ASN.1 und Apache Avro?

124

All dies bietet binäre Serialisierung, RPC-Frameworks und IDL. Ich interessiere mich für wichtige Unterschiede zwischen ihnen und Merkmalen (Leistung, Benutzerfreundlichkeit, Unterstützung von Programmiersprachen).

Wenn Sie andere ähnliche Technologien kennen, erwähnen Sie diese bitte in einer Antwort.

andreypopp
quelle
@ Zenikoder: Dieser Link enthält keine Informationen für 2 von 5 abgefragten Formaten.
NUR MEINE RICHTIGE MEINUNG
2
für diejenigen, die RPC nicht kennen - Remote Prodecure Call, IDL - Interface Definition Sprache
garg10may

Antworten:

97

ASN.1 ist ein ISO / ISE-Standard. Es hat eine sehr lesbare Ausgangssprache und eine Vielzahl von Back-Ends, sowohl binär als auch für Menschen lesbar. Als internationaler Standard (und noch dazu ein alter!) Ist die Ausgangssprache ein bisschen küchenspülend (ungefähr so ​​wie der Atlantik ein bisschen nass ist), aber sie ist extrem gut spezifiziert und hat eine anständige Menge an Unterstützung . (Sie können wahrscheinlich eine ASN.1-Bibliothek für jede Sprache finden, die Sie benennen, wenn Sie hart genug graben, und wenn nicht, sind gute C-Sprachbibliotheken verfügbar, die Sie in FFIs verwenden können.) Es ist eine standardisierte Sprache, obsessiv dokumentiert und hat auch ein paar gute Tutorials zur Verfügung.

Sparsamkeit ist kein Standard. Es stammt ursprünglich von Facebook und wurde später als Open-Source-Projekt bereitgestellt. Derzeit handelt es sich um ein Apache-Projekt der obersten Ebene. Es ist nicht gut dokumentiert - insbesondere in Tutorial-Levels - und zu meinem (zugegebenermaßen kurzen) Blick scheint es nichts hinzuzufügen, was andere, frühere Bemühungen noch nicht tun (und in einigen Fällen besser). Um fair zu sein, es hat eine ziemlich beeindruckende Anzahl von Sprachen, die es sofort unterstützt, einschließlich einiger der bekannteren Nicht-Mainstream-Sprachen. Die IDL ist auch vage C-ähnlich.

Protokollpuffer sind kein Standard. Es ist ein Google-Produkt, das für die breitere Community freigegeben wird. Es ist etwas eingeschränkt in Bezug auf Sprachen, die standardmäßig unterstützt werden (es unterstützt nur C ++, Python und Java), aber es bietet viel Unterstützung von Drittanbietern für andere Sprachen (von sehr variabler Qualität). Google erledigt so ziemlich seine gesamte Arbeit mit Protokollpuffern. Es handelt sich also um ein kampferprobtes, kampferprobtes Protokoll (wenn auch nicht so kampferprobt wie ASN.1). Es hat eine viel bessere Dokumentation als Thrift, ist aber ein Google-Produkt, es ist sehr wahrscheinlich instabil (im Sinne einer sich ständig ändernden, nicht im Sinne einer unzuverlässigen). Die IDL ist auch C-ähnlich.

Alle oben genannten Systeme verwenden ein in einer Art IDL definiertes Schema, um Code für eine Zielsprache zu generieren, der dann beim Codieren und Decodieren verwendet wird. Avro nicht. Die Typisierung von Avro ist dynamisch und die Schemadaten werden zur Laufzeit direkt sowohl zum Codieren als auch zum Decodieren verwendet (was einige offensichtliche Kosten bei der Verarbeitung, aber auch einige offensichtliche Vorteile gegenüber dynamischen Sprachen und das Fehlen der Notwendigkeit von Tagging-Typen usw. mit sich bringt). . Das Schema verwendet JSON, wodurch die Unterstützung von Avro in einer neuen Sprache etwas einfacher zu verwalten ist, wenn bereits eine JSON-Bibliothek vorhanden ist. Wie bei den meisten Protokollbeschreibungssystemen zur Neuerfindung von Rädern ist auch Avro nicht standardisiert.

Persönlich würde ich trotz meiner Hassliebe wahrscheinlich ASN.1 für die meisten RPC- und Nachrichtenübertragungszwecke verwenden, obwohl es keinen RPC-Stack gibt (Sie müssten einen erstellen, aber IOCs machen das einfach genug).

NUR MEINE RICHTIGE MEINUNG
quelle
3
Vielen Dank für die ausführliche Erklärung. Aber was ist mit der Versionierung? Ich habe gehört, dass Protobuf damit umgehen kann. Was ist mit anderen Bibliotheken und wie ist sie gemeinsam verwendbar? Außerdem scheint Avro jetzt zusätzlich zu JSON eine IDL mit C-ähnlicher Syntax zu haben.
andreypopp
2
ASN.1 unterstützt die manuelle Versionierung über die ...Erweiterungsmarkierungen oder die automatische Versionierung EXTENSIBILITY IMPLIEDim Modulkopf. Protocol Buffers, IIRC, unterstützt die manuelle Versionierung. Ich weiß nicht, ob es so etwas wie implizite Erweiterbarkeit unterstützt (und bin zu faul, um es nachzuschlagen). Thrift unterstützt auch einige Versionierungen, aber es scheint mir wieder ein manueller Prozess ohne die implizite Erweiterbarkeit zu sein.
NUR MEINE RICHTIGE MEINUNG
7
Für den Datensatz codieren Protokollpuffer Felder immer explizit nach Zahlen, und es ist niemals ein Fehler auf Bibliotheksebene, wenn zusätzliche Felder vorhanden sind, und fehlende Felder sind kein Fehler, wenn sie als optional oder explizit markiert sind. Somit haben alle Protokollpuffernachrichten EXTENSIBILITY IMPLIED.
Kevin Cathcart
mit IOCs - meinen Sie die Umkehrung der Kontrolle? Was würde man für RPC-Stack in PHP verwenden, so etwas wie eine XML-RPC-Erweiterung? oder müsste man etwas alleine schreiben?
Stann
4
Avro ist flexibler, da es entweder ermöglicht, dynamisch an definierten Schemata zu arbeiten oder Boilerplate-Klassen zu generieren. Nach meiner Erfahrung ist es sehr leistungsfähig: Seine Stärke liegt in seinen zahlreichen Funktionen, einschließlich des RPC-Generators (dies ist eine häufige Funktion von Thrift).
Paolo Maresca
38

Wir haben gerade eine interne Studie über Serialisierer durchgeführt. Hier sind einige Ergebnisse (auch für meine zukünftige Referenz!).

Sparsamkeit = Serialisierung + RPC-Stapel

Der größte Unterschied besteht darin, dass Thrift nicht nur ein Serialisierungsprotokoll ist, sondern ein ausgewachsener RPC-Stack, der einem modernen SOAP-Stack ähnelt. So nach der Serialisierung, die Objekte könnten (aber nicht vorgeschrieben) zwischen Maschinen über TCP / IP gesendet werden. In SOAP haben Sie mit einem WSDL-Dokument begonnen, das die verfügbaren Dienste (Remotemethoden) und die erwarteten Argumente / Objekte vollständig beschreibt. Diese Objekte wurden über XML gesendet. In Thrift beschreibt die .thrift-Datei die verfügbaren Methoden vollständig, erwartete Parameterobjekte und die Objekte werden über einen der verfügbaren Serializer serialisiert (wobei Compact Protocolein effizientes Binärprotokoll in der Produktion am beliebtesten ist).

ASN.1 = Großvater

ASN.1 wurde in den 80er Jahren von Telekommunikationsleuten entwickelt und ist aufgrund der eingeschränkten Bibliotheksunterstützung im Vergleich zu den jüngsten Serialisierern, die von CompSci-Leuten entwickelt wurden, umständlich zu verwenden. Es gibt zwei Varianten, die DER-Codierung (binär) und die PEM-Codierung (ascii). Beide sind schnell, aber DER ist schneller und größeneffizienter. Tatsächlich kann ASN.1 DER Serializer, die 30 Jahre lang entwickelt wurden, problemlos aufrechterhalten (und manchmal schlagen)nach sich selbst ein Beweis für sein ausgereiftes Design. Es ist sehr kompakt, kleiner als Protocol Buffers und Thrift und wird nur von Avro geschlagen. Das Problem besteht darin, großartige Bibliotheken zu unterstützen, und im Moment scheint Bouncy Castle die beste für C # / Java zu sein. ASN.1 ist König in Sicherheits- und Kryptosystemen und wird nicht verschwinden. Machen Sie sich also keine Sorgen um die Zukunftssicherheit. Holen Sie sich einfach eine gute Bibliothek ...

MessagePack = Mitte des Pakets

Es ist nicht schlecht, aber es ist weder das schnellste noch das kleinste noch das am besten unterstützte. Kein Produktionsgrund, es zu wählen.

Verbreitet

Darüber hinaus sind sie ziemlich ähnlich. Die meisten sind Varianten des TLV: Type-Length-ValueGrundprinzips.

Protokollpuffer (von Google stammend), Avro (Apache-basiert, in Hadoop verwendet), Thrift (von Facebook, jetzt Apache-Projekt) und ASN.1 (von Telecom stammend) beinhalten alle eine gewisse Codegenerierungsebene, bei der Sie Ihre Daten zuerst in einem Serializer ausdrücken -spezifisches Format, dann generiert der Serializer "Compiler" über die code-genPhase Quellcode für Ihre Sprache . Ihre App-Quelle verwendet diese code-genKlassen dann für E / A. Beachten Sie, dass Sie mit bestimmten Implementierungen (z. B. der Avro-Bibliothek von Microsoft oder ProtoBuf.NET von Marc Gavel) Ihre POCO / POJO-Objekte auf App-Ebene direkt dekorieren können. Anschließend verwendet die Bibliothek diese dekorierten Klassen direkt anstelle der Klassen eines Code-Gens. Wir haben gesehen, dass dieses Angebot die Leistung steigert, da es eine Objektkopierphase eliminiert (von POCO / POJO-Feldern auf Anwendungsebene bis zu Feldern mit Code-Gen).

Einige Ergebnisse und ein Live-Projekt zum Spielen

Dieses Projekt ( https://github.com/sidshetye/SerializersCompare ) vergleicht wichtige Serializer in der C # -Welt. Die Java-Leute haben schon etwas Ähnliches .

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!)
DeepSpace101
quelle
3
ASN.1 verfügt außerdem über BER (Basic Encoding Rules), PER (Packed Encoding Rules) und XER (XML Encoding Rules). DER ist eine Variante von BER, die hauptsächlich für die Kryptographie verwendet wird, da sie eine eindeutige Codierung für jedes Datum garantiert. Sowohl BER als auch PER können effizienter sein als DER. Die meisten Bibliotheken verarbeiten DER. Einige behandeln nicht alle BER-Konstrukte korrekt. Für diejenigen, die mehr erfahren möchten
Joe Steele
Es hat auch JER - JavaScript Object Notation Encoding Rules. Sie können auch Ihre eigenen Codierungsregeln mit ECN (Encoding Control Notation) definieren. Gute Liste der Spezifikationen mit Download-Links: oss.com/asn1/resources/standards-define-asn1.html
Dmitry
There are two variants, DER (binary) encoding and PEM (ascii) encoding. Beachten Sie, dass PEM nur eine Base-64-codierte Binärdaten in BEGIN END-Kommentaren ist. Diese Binärdaten wurden möglicherweise mithilfe der DER-Codierung generiert, daher ist es seltsam, PEM und DER zu vergleichen.
RafalS
14

Zusätzlich zur Leistungsperspektive hat Uber kürzlich mehrere dieser Bibliotheken in ihrem Engineering-Blog bewertet:

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

Der Gewinner für sie? MessagePack + zlib zur Komprimierung

Unser Ziel war es, die Kombination aus Codierungsprotokoll und Komprimierungsalgorithmus mit dem kompaktesten Ergebnis bei höchster Geschwindigkeit zu finden. Wir haben Kombinationen aus Codierungsprotokoll und Komprimierungsalgorithmus auf 2.219 pseudozufälligen anonymisierten Reisen von Uber New York City (in einer Textdatei als JSON abgelegt) getestet.

Die Lehre hier ist, dass Ihre Anforderungen bestimmen, welche Bibliothek für Sie geeignet ist. Für Uber konnten sie aufgrund der schemenlosen Art der Nachrichtenübermittlung kein IDL-basiertes Protokoll verwenden. Dies beseitigte eine Reihe von Optionen. Auch für sie kommt nicht nur die rohe Kodierungs- / Dekodierungszeit ins Spiel, sondern auch die Größe der Daten in Ruhe.

Größenergebnisse

Größenergebnisse

Geschwindigkeitsergebnisse

Geben Sie hier die Bildbeschreibung ein

Avner
quelle
13

Das einzige große an ASN.1 ist, dass es für die Spezifikation und nicht für die Implementierung ausgelegt ist. Daher ist es sehr gut darin, Implementierungsdetails in jeder "echten" Programmiersprache zu verbergen / zu ignorieren.

Es ist die Aufgabe des ASN.1-Compilers, Codierungsregeln auf die asn1-Datei anzuwenden und aus beiden ausführbaren Code zu generieren. Die Kodierungsregeln können in der Kodierungsnotation (ECN) angegeben sein oder eine der standardisierten Regeln wie BER / DER, PER, XER / EXER sein. Das heißt, ASN.1 sind die Typen und Strukturen, die Codierungsregeln definieren die Codierung auf der Leitung, und nicht zuletzt überträgt der Compiler sie in Ihre Programmiersprache.

Die kostenlosen Compiler unterstützen meines Wissens C, C ++, C #, Java und Erlang. Die (viel zu teuren und patent- / lizenzpflichtigen) kommerziellen Compiler sind sehr vielseitig, normalerweise absolut aktuell und unterstützen manchmal sogar noch mehr Sprachen, sehen aber ihre Websites (OSS Nokalva, Marben usw.).

Mit diesen Techniken ist es überraschend einfach, eine Schnittstelle zwischen Parteien völlig unterschiedlicher Programmierkulturen (z. B. "eingebettete" Personen und "Serverfarmer") anzugeben: eine asn.1-Datei, die Codierungsregel, z. B. BER, und z. B. ein UML-Interaktionsdiagramm . Keine Sorge, wie es implementiert wird, lassen Sie alle "ihr Ding" benutzen! Bei mir hat es sehr gut geklappt. Übrigens: Auf der Website von OSS Nokalva finden Sie möglicherweise mindestens zwei kostenlos herunterladbare Bücher über ASN.1 (eines von Larmouth, das andere von Dubuisson).

IMHO versuchen die meisten anderen Produkte nur, noch ein weiterer RPC-Stub-Generator zu sein, der viel Luft in das Serialisierungsproblem pumpt. Nun, wenn man das braucht, könnte es einem gut gehen. Aber für mich sehen sie aus wie Neuerfindungen von Sun-RPC (ab Ende der 80er Jahre), aber hey, das hat auch gut funktioniert.

njimko
quelle
7

Microsoft Bond ( https://github.com/Microsoft/bond ) beeindruckt durch Leistung, Funktionen und Dokumentation. Derzeit werden jedoch nicht viele Zielplattformen unterstützt (13. Februar 2015). Ich kann nur davon ausgehen, dass es sehr neu ist. Derzeit unterstützt es Python, C # und C ++. Es wird von MS überall verwendet. Ich habe es versucht, für mich als AC # -Entwickler ist die Verwendung von Bond besser als die Verwendung von Protobuf, aber ich habe auch Sparsamkeit verwendet. Das einzige Problem, mit dem ich konfrontiert war, war die Dokumentation. Ich musste viele Dinge ausprobieren, um zu verstehen, wie Dinge gemacht werden.

Es gibt nur wenige Ressourcen für Bond wie folgt ( https://news.ycombinator.com/item?id=8866694 , https://news.ycombinator.com/item?id=8866848 , https://microsoft.github.io/ bond / why_bond.html )

Srivathsa Harish Venkataramana
quelle
5

Für die Leistung ist ein Datenpunkt der JVM-Serializer- Benchmark - es handelt sich um ganz bestimmte, kleine Nachrichten, die jedoch hilfreich sein können, wenn Sie sich auf einer Java-Plattform befinden. Ich denke, Leistung im Allgemeinen ist oft nicht der wichtigste Unterschied. Außerdem: Nimm die Worte der Autoren NIEMALS als Evangelium; Viele beworbene Behauptungen sind gefälscht (die msgpack-Site hat zum Beispiel einige zweifelhafte Behauptungen; sie mag schnell sein, aber die Informationen sind sehr lückenhaft, der Anwendungsfall nicht sehr realistisch).

Ein großer Unterschied besteht darin, ob ein Schema verwendet werden muss (PB, mindestens Thrift; Avro kann optional sein; ASN.1 denke ich auch; MsgPack, nicht unbedingt).

Außerdem: Meiner Meinung nach ist es gut, ein mehrschichtiges, modulares Design verwenden zu können. Das heißt, die RPC-Schicht sollte nicht das Datenformat oder die Serialisierung vorgeben. Leider bündeln die meisten Kandidaten diese eng.

Schließlich schließt die Leistung bei der Auswahl des Datenformats heutzutage die Verwendung von Textformaten nicht aus. Es gibt blitzschnelle JSON-Parser (und ziemlich schnelle XML-Streaming-Parser). Wenn man die Interoperabilität von Skriptsprachen und die Benutzerfreundlichkeit berücksichtigt, sind Binärformate und -protokolle möglicherweise nicht die beste Wahl.

StaxMan
quelle
Vielen Dank für den Erfahrungsaustausch, aber ich denke, ich brauche noch ein Binärformat (ich habe eine wirklich große Datenmenge) und werde wahrscheinlich bei Avro bleiben.
andreypopp
Ja, dann kann es Sinn machen. Möglicherweise möchten Sie die Komprimierung unabhängig vom zu verwendenden Format verwenden (LZF ist hilfreich, da es im Vergleich zu gzip / deflate sehr schnell komprimiert / dekomprimiert werden kann).
StaxMan