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


124

Tous ces éléments fournissent une sérialisation binaire, des frameworks RPC et IDL. Je m'intéresse aux principales différences entre eux 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.



@Zenikoder: Ce lien ne contient aucune information pour 2 des 5 formats interrogés.
JUSTE MON OPINION correcte


2
pour ceux qui ne connaissent pas RPC - Remote Prodecure Call, IDL - Interface Definition language
garg10may

Réponses:


97

ASN.1 est une norme ISO / ISE. Il a un langage source très lisible et une variété de back-ends, à la fois binaires et lisibles par l'homme. Étant une norme internationale (et ancienne en plus!), La langue source est un peu folle de cuisine (à peu près 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 offre un support décent . (Vous pouvez probablement trouver une bibliothèque ASN.1 pour n'importe quel langage que vous nommez si vous creusez assez dur, et sinon il y a de bonnes bibliothèques de langage C disponibles que vous pouvez utiliser dans les FFI.) C'est, étant un langage standardisé, documenté de manière obsessionnelle et a également quelques bons tutoriels disponibles.

L'économie 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. Ce n'est pas bien documenté - en particulier les niveaux de tutoriel - et à mon (certes bref) coup d'œil ne semble pas ajouter quoi que ce soit que d'autres efforts précédents ne font pas déjà (et dans certains cas mieux). Pour être juste, il a un nombre assez impressionnant de langues qu'il prend en charge hors de la boîte, y compris quelques-unes des langues non traditionnelles les plus en vue. L'IDL est également vaguement semblable au C.

Protocol Buffers n'est pas une norme. C'est un produit Google qui est lancé à la communauté au sens large. Il est un peu limité en termes de langages pris en charge hors de la boîte (il ne prend en charge que C ++, Python et Java) mais il a beaucoup de support tiers pour d'autres langages (de qualité très variable). Google fait à peu près tout son travail en utilisant des tampons de protocole, il s'agit donc d'un protocole éprouvé et endurci au combat (même s'il n'est pas aussi dur que l'ASN.1. Il a une bien meilleure documentation que Thrift, mais, étant un Produit Google, il est très probable qu'il soit instable (dans le sens d'une constante évolution, et non dans le sens de non fiable). L'IDL est également similaire à 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 l'encodage 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 directement à l'exécution pour encoder et décoder (ce qui a des coûts évidents de traitement, mais aussi des avantages évidents vis-à-vis des langages dynamiques et l'absence de besoin de types de balisage, etc.) . Son schéma utilise JSON, ce qui rend la prise en charge d'Avro dans un nouveau langage un peu plus facile à gérer s'il existe déjà une bibliothèque JSON. Encore une fois, comme avec la plupart des systèmes de description de protocole qui réinventent la roue, Avro n'est pas non plus standardisé.

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


3
Merci pour une explication détaillée. Mais qu'en est-il du contrôle de version, j'ai entendu dire que protobuf pouvait gérer cela, qu'en est-il des autres bibliothèques et comment il est utilisable en commun? En outre, il semble qu'Avro dispose désormais d'IDL avec une syntaxe de type C en plus de celle de JSON.
andreypopp

2
ASN.1 prend en charge la gestion des versions manuelle via les ...marqueurs d'extension ou via automatique EXTENSIBILITY IMPLIEDdans l'en-tête du module. Protocol Buffers, IIRC, prend en charge la gestion manuelle des versions. Je ne sais pas s'il prend en charge quelque chose comme l'extensibilité implicite (et je suis trop paresseux pour le rechercher). Thrift prend également en charge certaines versions, mais encore une fois, cela me semble être un processus manuel sans l'extensibilité implicite.
JUSTE MON OPINION correcte

7
Pour l'enregistrement, Protocol Buffers encode toujours explicitement les champs par des nombres, et ce n'est jamais une erreur au niveau de la bibliothèque s'il y a des champs supplémentaires, et les champs manquants ne sont pas une erreur s'ils sont marqués facultatifs ou explicites. Ainsi, tous les messages de tampons de protocole ont EXTENSIBILITY IMPLIED.
Kevin Cathcart

par les CIO - voulez-vous dire l'inversion du contrôle? qu'utiliserait-on pour la pile RPC en PHP, quelque chose comme l'extension XML-RPC? ou il faudrait écrire quelque chose seul?
Stann

4
Avro est plus flexible car il permet soit de travailler dynamiquement sur un schéma défini, soit de générer des classes standard. D'après mon expérience, il est très puissant: sa force réside dans son riche ensemble de fonctionnalités, dont le générateur RPC (c'est une fonctionnalité commune avec Thrift).
Paolo Maresca

38

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 pile SOAP moderne. Ainsi, après la sérialisation, les objets pourraient (mais pas obligatoires) être envoyés 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 complètement 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 des spécialistes des télécommunications dans les années 80 et est difficile à utiliser en raison du support limité des bibliothèques par rapport aux récents sérialiseurs qui ont émergé des gens de CompSci. Il existe deux variantes, le codage DER (binaire) et le codage PEM (ascii). Les deux sont rapides, mais le DER est plus rapide et plus efficace en termes de taille. En fait, ASN.1 DER peut facilement suivre (et parfois battre) les sérialiseurs conçus depuis 30 ans après lui-même, ce qui témoigne de sa conception bien conçue. Il est très compact, plus petit que Protocol Buffers et Thrift, battu uniquement par Avro. Le problème est d'avoir d'excellentes bibliothèques à prendre en charge et pour le moment, Bouncy Castle semble être la meilleure pour C # / Java. 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 `` future preuve ''. Procurez-vous simplement 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 mieux supporté. Aucune raison de production pour le choisir.

Commun

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

Protocol Buffers (origine Google), Avro (basé sur Apache, utilisé dans Hadoop), Thrift (origine Facebook, maintenant projet Apache) et ASN.1 (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 -spécifique, alors le sérialiseur "compilateur" générera le code source de votre langage via la code-genphase. La source de votre application utilise ensuite ces code-genclasses 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 les objets POCO / POJO au niveau de votre 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 de niveau application aux champs code-gen).

Quelques résultats et un projet live avec lequel jouer

Ce projet ( https://github.com/sidshetye/SerializersCompare ) compare les sérialiseurs importants dans le monde C #. Les gens de 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!)

3
ASN.1 a également BER (Basic Encoding Rules), PER (Packed Encoding Rules) et XER (XML Encoding Rules). DER est une variante de BER qui est principalement utilisée pour la cryptographie car elle garantit un encodage unique pour chaque donnée. Le BER et le PER peuvent être plus efficaces que le DER. La plupart des bibliothèques traitent DER. Certains ne gèrent pas correctement toutes les constructions BER. Pour ceux qui souhaitent en savoir plus: luca.ntop.org/Teaching/Appunti/asn1.html
Joe Steele

Il a également JER - Règles d'encodage de notation d'objets JavaScript. Vous pouvez également définir vos propres règles d'encodage avec ECN (Encoding Control Notation). Bonne liste de spécifications avec des liens de téléchargement: oss.com/asn1/resources/standards-define-asn1.html
Dmitry

There are two variants, DER (binary) encoding and PEM (ascii) encoding. Gardez à l'esprit que PEM n'est qu'une donnée binaire encodée en base 64 dans les commentaires BEGIN END. Ces données binaires ont peut-être été générées à l'aide du codage DER, il est donc étrange de comparer PEM et DER.
RafalS

14

Pour ajouter à la perspective des performances, Uber a récemment évalué plusieurs de ces bibliothèques sur son 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 2219 voyages anonymisés pseudo-aléatoires depuis Uber New York City (mis 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éma du passage des messages qu'ils ont. Cela a éliminé un tas d'options. Aussi pour eux, ce n'est pas seulement le temps de codage / décodage brut qui entre en jeu, mais la taille des données au repos.

Résultats de taille

Résultats de taille

Résultats de vitesse

entrez la description de l'image ici


13

La seule grande chose à propos d'ASN.1 est qu'il est conçu pour la spécification et non pour l' implémentation. Par conséquent, il est très bon pour cacher / ignorer les détails d'implémentation dans n'importe quel langage de programmation «réel».

C'est le travail du compilateur ASN.1 d'appliquer des règles d'encodage au fichier asn1 et de générer à partir de ces deux codes exécutables. Les règles de codage peuvent être données en notation d'encodage (ECN) ou peuvent être l'une des règles normalisées telles que BER / DER, PER, XER / EXER. C'est 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 dans 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 à jour et supportent parfois 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 "embarquées" et des "fermiers de serveurs") en utilisant ces techniques: un fichier asn.1, la règle d'encodage par exemple BER et un diagramme d'interaction UML par exemple . Ne vous inquiétez pas de la façon dont il est mis en œuvre, laissez chacun utiliser "son 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 essaient seulement d'être encore-un autre-RPC-stub-générateurs, pompant beaucoup d'air dans le problème de sérialisation. Eh bien, si on en a besoin, ça ira peut-être. Mais pour moi, ils ressemblent à des réinventions de Sun-RPC (de la fin des années 80), mais, hé, cela a bien fonctionné aussi.


7

Bond 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 ac #, l'utilisation de bond est meilleure que l'utilisation de protobuf, mais j'ai également utilisé de l'épargne, le seul problème auquel j'ai été confronté était avec la documentation, j'ai dû essayer beaucoup de choses pour comprendre comment les choses sont faites.

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 )


5

Pour les performances, un point de données est le benchmark jvm-serializers - il s'agit de petits messages assez spécifiques, mais qui pourraient vous aider si vous êtes sur la plate-forme Java. Je pense que la performance en général ne sera souvent pas la différence la plus importante. Aussi: NE JAMAIS prendre les paroles des auteurs comme évangile; de nombreuses revendications annoncées sont fausses (le site msgpack par exemple a des revendications douteuses; cela 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 cela 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; autrement dit, 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 actuelles n'empêchent pas l'utilisation de formats textuels. Il existe des analyseurs JSON ultra-rapides (et des analyseurs XML en streaming assez rapides); et lorsque l'on considère l'interopérabilité des langages de script et la facilité d'utilisation, les formats et protocoles binaires peuvent ne pas être le meilleur choix.


Merci pour le partage d'expériences, mais je pense que j'ai toujours besoin d'un format binaire (j'ai une quantité vraiment énorme de données) et je vais probablement m'en tenir à Avro.
andreypopp

Ouais peut-être logique alors. Vous pouvez utiliser la compression à tout moment, quel que soit le format à utiliser (LZF est bien car il est très rapide à compresser / décompresser, par rapport à gzip / deflate).
StaxMan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.