web-dev-qa-db-fra.com

Quelles sont les principales différences entre Apache Thrift, Google Protocol Buffers, MessagePack, ASN.1 et Apache Avro?

Tous ces éléments fournissent une sérialisation binaire, des cadres RPC et IDL. Je suis intéressé par les principales différences entre elles et leurs caractéristiques (performances, facilité d'utilisation, prise en charge des langages de programmation).

Si vous connaissez d'autres technologies similaires, veuillez le mentionner dans une réponse.

121
andreypopp

ASN.1 est une norme ISO/ISE. Il a un langage source très lisible et une variété de back-end, à la fois binaires et lisibles par l'homme. Étant une norme internationale (et une ancienne à cela!), La langue source est un peu évasive (de la même manière que l'océan Atlantique est un peu humide) mais elle est extrêmement bien spécifiée et bénéficie d'un support décent . (Vous pouvez probablement trouver une bibliothèque ASN.1 pour n'importe quelle langue que vous nommez si vous creusez assez fort, et sinon il y a de bonnes bibliothèques de langage C disponibles que vous pouvez utiliser dans les FFI.) C'est un langage standardisé, documenté de manière obsessionnelle et propose également quelques bons didacticiels.

Thrift n'est pas une norme. Il est à l'origine de Facebook et a ensuite été open source et est actuellement un projet Apache de haut niveau. Il n'est pas bien documenté - en particulier les niveaux de didacticiel - et à mon avis (certes bref) ne semble rien ajouter d'autre, les efforts précédents ne le font pas déjà (et dans certains cas mieux). Pour être honnête, il a un nombre assez impressionnant de langues qu'il prend en charge, y compris quelques-unes des plus importantes non conventionnelles. L'IDL est également vaguement en forme de C.

Protocol Buffers n'est pas une norme. Il s'agit d'un produit Google qui est mis à la disposition de la communauté au sens large. Il est un peu limité en termes de langues prises en charge (il ne prend en charge que C++, Python et Java) mais il a beaucoup de support tiers pour d'autres langues (de très Google fait à peu près tout son travail à l'aide de tampons de protocole, il s'agit donc d'un protocole éprouvé et éprouvé (bien qu'il ne soit pas aussi endurci que ASN.1). Sa documentation est bien meilleure que Thrift, mais, étant un produit Google, il est très susceptible d'être instable (dans le sens d'une évolution constante, pas dans le sens d'un manque de fiabilité). L'IDL est également semblable à C.

Tous les systèmes ci-dessus utilisent un schéma défini dans une sorte d'IDL pour générer du code pour un langage cible qui est ensuite utilisé dans le codage et le décodage. Avro ne le fait pas. Le typage d'Avro est dynamique et ses données de schéma sont utilisées au moment de l'exécution directement à la fois pour coder et décoder (ce qui a des coûts évidents de traitement, mais aussi des avantages évidents vis-à-vis des langages dynamiques et un manque de besoin de types de balisage, etc.) . Son schéma utilise JSON, ce qui facilite la prise en charge d'Avro dans une nouvelle langue s'il existe déjà une bibliothèque JSON. Encore une fois, comme avec la plupart des systèmes de description de protocole réinventant la roue, Avro n'est pas non plus standardisé.

Personnellement, malgré ma relation amoureuse/haineuse avec lui, j'utiliserais probablement ASN.1 pour la plupart des RPC et la transmission de messages, bien qu'il n'ait pas vraiment de pile RPC (il faudrait en faire une, mais les IOC le font assez simple).

95

Nous venons de faire une étude interne sur les sérialiseurs, voici quelques résultats (pour ma future référence aussi!)

Thrift = sérialisation + pile RPC

La plus grande différence est que Thrift n'est pas seulement un protocole de sérialisation, c'est une pile RPC complète qui ressemble à une époque moderne SOAP pile. Donc après la sérialisation, les objets pourrait (mais pas obligatoire) être envoyé entre les machines via TCP/IP. Dans SOAP, vous avez commencé avec un document WSDL qui décrit entièrement les services disponibles (méthodes distantes) et les arguments/objets attendus. Ces objets ont été envoyés via XML. Dans Thrift, le fichier .thrift décrit entièrement les méthodes disponibles, les objets paramètres attendus et les objets sont sérialisés via l'un des sérialiseurs disponibles (avec Compact Protocol, un protocole binaire efficace, étant le plus populaire en production).

ASN.1 = Grand-papa

ASN.1 a été conçu par les opérateurs télécoms dans les années 80 et est maladroit à utiliser en raison du support limité de la bibliothèque par rapport aux sérialiseurs récents issus des utilisateurs de CompSci. Il existe deux variantes, le codage DER (binaire) et le codage PEM (ascii). Les deux sont rapides, mais DER est plus rapide et plus efficace en termes de taille des deux. En fait, ASN.1 DER peut facilement suivre (et parfois battre) les sérialiseurs qui ont été conçus - 30 ans après lui-même, un témoignage de sa conception bien conçue. Il est très compact, plus petit que les tampons de protocole et Thrift, seulement battu par Avro. Le problème est d'avoir de bonnes bibliothèques à prendre en charge et en ce moment, Bouncy Castle semble être le meilleur pour C #/Java. L'ASN.1 est le roi des systèmes de sécurité et de cryptographie et ne va pas disparaître, alors ne vous inquiétez pas pour la "pérennisation". Obtenez juste une bonne bibliothèque ...

MessagePack = milieu du pack

Ce n'est pas mal mais ce n'est ni le plus rapide, ni le plus petit ni le meilleur supporté. Aucune raison de production pour le choisir.

Commun

Au-delà, ils sont assez similaires. La plupart sont des variantes de la base TLV: Type-Length-Value principe.

Les tampons de protocole (d'origine Google), Avro (basé sur Apache, utilisé dans Hadoop), Thrift (d'origine Facebook, maintenant le projet Apache) et ASN.1 (d'origine Telecom) impliquent tous un certain niveau de génération de code où vous exprimez d'abord vos données dans un sérialiseur format spécifique, le "compilateur" du sérialiseur générera le code source de votre langue via le code-gen phase. La source de votre application utilise ensuite ces code-gen classes pour IO. Notez que certaines implémentations (par exemple: la bibliothèque Avro de Microsoft ou ProtoBuf.NET de Marc Gavel) vous permettent de décorer directement vos objets POCO/POJO au niveau de l'application, puis la bibliothèque utilise directement ces classes décorées au lieu des classes de code-gen. Nous avons vu cela offrir une amélioration des performances car il élimine une étape de copie d'objet (des champs POCO/POJO au niveau de l'application aux champs de code-gen).

Quelques résultats et un projet live pour jouer avec

Ce projet ( https://github.com/sidshetye/SerializersCompare ) compare les sérialiseurs importants du monde C #. Les gens Java ont déjà quelque chose de similaire .

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

Ajoutant à la perspective des performances, Uber a récemment évalué plusieurs de ces bibliothèques sur leur blog d'ingénierie:

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

Le gagnant pour eux? MessagePack + zlib pour la compression

Notre objectif était de trouver la combinaison du protocole de codage et de l'algorithme de compression avec le résultat le plus compact à la vitesse la plus élevée. Nous avons testé des combinaisons de protocoles de codage et d'algorithmes de compression sur 2 219 trajets anonymisés pseudo-aléatoires d'Uber New York City (placés dans un fichier texte au format JSON).

La leçon ici est que vos besoins déterminent la bibliothèque qui vous convient. Pour Uber, ils ne pouvaient pas utiliser un protocole basé sur IDL en raison de la nature sans schémas du passage de messages qu'ils ont. Cela a éliminé un tas d'options. Pour eux, ce n'est pas seulement le temps d'encodage/décodage brut qui entre en jeu, mais la taille des données au repos.

Résultats de taille

Size Results

Résultats de vitesse

enter image description here

12
Avner

La seule chose importante à propos d'ASN.1 est que ist est conçu pour spécification pas l'implémentation. Par conséquent, il est très bon pour masquer/ignorer les détails d'implémentation dans n'importe quel "vrai" langage de programmation.

C'est le travail du compilateur ASN.1 d'appliquer les règles d'encodage au fichier asn1 et de générer à partir des deux du code exécutable. Les règles d'encodage peuvent être données dans la notation EnCoding (ECN) ou peuvent être l'une des normes standardisées telles que BER/DER, PER, XER/EXER. C'est-à-dire que l'ASN.1 est les types et les structures, les règles d'encodage définissent l'encodage sur le fil, et enfin le compilateur le transfère à votre langage de programmation.

Les compilateurs gratuits prennent en charge C, C++, C #, Java et Erlang à ma connaissance. Les compilateurs commerciaux (beaucoup trop chers et soumis à des brevets/licences) sont très polyvalents, généralement absolument à jour et prennent parfois en charge encore plus de langues, mais consultez leurs sites (OSS Nokalva, Marben, etc.).

Il est étonnamment facile de spécifier une interface entre des parties de cultures de programmation totalement différentes (par exemple, des personnes "intégrées" et des "serveurs de serveurs") en utilisant ces techniques: un fichier asn.1, la règle d'encodage, par exemple BER et un exemple Diagramme d'interaction UML. Ne vous inquiétez pas de la façon dont il est mis en œuvre, laissez tout le monde utiliser "leur truc"! Pour moi, cela a très bien fonctionné. Btw .: Sur le site d'OSS Nokalva, vous pouvez trouver au moins deux livres gratuits à télécharger sur ASN.1 (l'un de Larmouth l'autre de Dubuisson).

À mon humble avis, la plupart des autres produits n'essaient que d'être des générateurs de moignons encore un autre RPC, pompant beaucoup d'air dans le problème de sérialisation. Eh bien, si on en a besoin, on pourrait être bien. Mais pour moi, ils ressemblent à des réinventions de Sun-RPC (à partir de la fin des années 80), mais bon, ça a bien fonctionné aussi.

11
njimko

Le lien de Microsoft ( https://github.com/Microsoft/bond ) est très impressionnant avec ses performances, ses fonctionnalités et sa documentation. Cependant, il ne prend pas en charge de nombreuses plates-formes cibles pour le moment (13 février 2015). Je ne peux que supposer que c'est parce que c'est très nouveau. actuellement, il prend en charge python, c # et c ++. Il est utilisé par MS partout. Je l'ai essayé, pour moi en tant que développeur c #, utiliser Bond est mieux que d'utiliser Protobuf, mais j'ai également utilisé Thrift, le seul problème que j'ai rencontré était avec la documentation, j'ai dû essayer beaucoup de choses pour comprendre comment les choses se font.

Peu de ressources sur Bond sont les suivantes ( https://news.ycombinator.com/item?id=8866694 , https://news.ycombinator.com/item?id=8866848 , https://Microsoft.github.io/bond/why_bond.html )

Pour les performances, un point de données est jvm-serializers benchmark - il est assez spécifique, de petits messages, mais pourrait aider si vous êtes sur la plateforme Java. Je pense que les performances dans général ne sera souvent pas la différence la plus importante. Aussi: NE JAMAIS prendre les mots des auteurs comme évangile; de ​​nombreuses allégations annoncées sont fausses (le site msgpack par exemple a des affirmations douteuses; il peut être rapide, mais les informations sont très sommaires, le cas d'utilisation n'est pas très réaliste).

Une grande différence est de savoir si un schéma doit être utilisé (PB, Thrift au moins; Avro, il peut être facultatif; ASN.1 je pense aussi; MsgPack, pas nécessairement).

Aussi: à mon avis, il est bon de pouvoir utiliser une conception modulaire en couches; c'est-à-dire que la couche RPC ne doit pas dicter le format des données, la sérialisation. Malheureusement, la plupart des candidats les regroupent étroitement.

Enfin, lors du choix du format de données, les performances n'empêchent pas aujourd'hui l'utilisation de formats textuels. Il existe des analyseurs JSON extrêmement rapides (et des analyseurs XML en streaming assez rapides); et lorsque l'on considère l'interopérabilité à partir des langages de script et la facilité d'utilisation, les formats et protocoles binaires peuvent ne pas être le meilleur choix.

5
StaxMan