¿Cuáles son las diferencias clave entre Apache Thrift, Google Protocol Buffers, MessagePack, ASN.1 y Apache Avro?

124

Todos estos proporcionan serialización binaria, marcos RPC e IDL. Estoy interesado en las diferencias clave entre ellos y las características (rendimiento, facilidad de uso, soporte de lenguajes de programación).

Si conoce otras tecnologías similares, menciónelo en una respuesta.

andreypopp
fuente
@Zenikoder: Ese enlace no tiene ninguna información para 2 de 5 formatos consultados.
SOLO MI OPINIÓN correcta
2
para aquellos que no conocen RPC - Llamada remota de Prodecure, IDL - Lenguaje de definición de interfaz
garg10may

Respuestas:

97

ASN.1 es un estándar ISO / ISE. Tiene un lenguaje fuente muy legible y una variedad de back-end, tanto binarios como legibles por humanos. Al ser un estándar internacional (¡y antiguo!), El idioma de origen es un poco complicado para la cocina (casi de la misma manera que el Océano Atlántico está un poco húmedo) pero está extremadamente bien especificado y tiene una cantidad decente de soporte . (Probablemente pueda encontrar una biblioteca ASN.1 para cualquier idioma que nombre si profundiza lo suficiente, y si no, hay buenas bibliotecas de lenguaje C disponibles que puede usar en las FFI). Es un lenguaje estandarizado, obsesivamente documentado y tiene algunos buenos tutoriales disponibles también.

El ahorro no es un estándar. Es originalmente de Facebook y luego fue de código abierto y actualmente es un proyecto de Apache de alto nivel. No está bien documentado, especialmente los niveles de tutoría, y a mi parecer (sin duda breve) no parece agregar nada que otros esfuerzos anteriores ya no hacen (y en algunos casos mejor). Para ser justos, tiene una cantidad bastante impresionante de idiomas que admite de forma inmediata, incluidos algunos de los de mayor perfil no convencionales. El IDL también es vagamente similar a C.

Protocol Buffers no es un estándar. Es un producto de Google que se está lanzando a la comunidad en general. Es un poco limitado en términos de lenguajes admitidos de fábrica (solo es compatible con C ++, Python y Java) pero tiene una gran cantidad de soporte de terceros para otros lenguajes (de calidad muy variable). Google hace casi todo su trabajo utilizando Protocol Buffers, por lo que es un protocolo probado en batalla, aunque no tan duro como ASN.1. Tiene una documentación mucho mejor que Thrift, pero, siendo un Producto de Google, es muy probable que sea inestable (en el sentido de un cambio constante, no en el sentido de no confiable). El IDL también es similar a C.

Todos los sistemas anteriores usan un esquema definido en algún tipo de IDL para generar código para un idioma de destino que luego se usa en la codificación y decodificación. Avro no. El tipeo de Avro es dinámico y sus datos de esquema se usan en tiempo de ejecución directamente tanto para codificar como para decodificar (lo que tiene algunos costos obvios en el procesamiento, pero también algunos beneficios obvios frente a los lenguajes dinámicos y la falta de necesidad de etiquetar tipos, etc.) . Su esquema usa JSON, lo que hace que sea más fácil administrar Avro en un nuevo idioma si ya hay una biblioteca JSON. Nuevamente, como con la mayoría de los sistemas de descripción de protocolos de reinvención de ruedas, Avro tampoco está estandarizado.

Personalmente, a pesar de mi relación de amor / odio con él, probablemente usaría ASN.1 para la mayoría de los propósitos de transmisión de mensajes y RPC, aunque en realidad no tiene una pila de RPC (tendrías que hacer uno, pero los COI hacen que Suficientemente simple).

SOLO MI OPINIÓN correcta
fuente
3
Gracias por una explicación detallada. Pero, ¿qué pasa con las versiones? Escuché que protobuf puede manejar eso, ¿qué pasa con otras bibliotecas y cómo se puede usar en común? Además, parece que Avro ahora tiene IDL con sintaxis tipo C además de JSON one.
andreypopp
2
ASN.1 admite la versión manual a través de los ...marcadores de extensión o automática a través EXTENSIBILITY IMPLIEDdel encabezado del módulo. Protocol Buffers, IIRC, admite versiones manuales. No sé si es compatible con algo como la extensibilidad implícita (y soy demasiado vago para buscarlo). Thrift también admite algunas versiones, pero nuevamente me parece un proceso manual sin la extensibilidad implícita.
SOLO MI OPINIÓN correcta
77
Para el registro, Protocol Buffers siempre codifica explícitamente los campos por números, y nunca es un error a nivel de la biblioteca si hay campos adicionales, y los campos faltantes no son un error si están marcados como opcionales o explícitos. Por lo tanto todos los mensajes de protocolo tampones tienen EXTENSIBILITY IMPLIED.
Kevin Cathcart
por COI: ¿quiere decir inversión de control? ¿Qué se usaría para la pila RPC en PHP, algo así como la extensión XML-RPC? o uno tendría que escribir algo por sí mismo?
Stann
44
Avro es más flexible porque permite trabajar dinámicamente en un esquema definido o generar clases repetitivas. Desde mi experiencia, es muy poderoso: su fuerza reside en su rico conjunto de características, incluido el generador RPC (esta es una característica común con Thrift).
Paolo Maresca
38

Acabamos de hacer un estudio interno sobre serializadores, aquí hay algunos resultados (¡para mi referencia futura también!)

Ahorro = serialización + pila RPC

La mayor diferencia es que Thrift no es solo un protocolo de serialización, es una pila RPC completa que es como una pila SOAP moderna. Entonces, después de la serialización, los objetos podrían (pero no obligatorios) enviarse entre máquinas a través de TCP / IP. En SOAP, comenzó con un documento WSDL que describe completamente los servicios disponibles (métodos remotos) y los argumentos / objetos esperados. Esos objetos fueron enviados a través de XML. En Thrift, el archivo .thrift describe completamente los métodos disponibles, los objetos de parámetros esperados y los objetos se serializan a través de uno de los serializadores disponibles (conCompact Protocol un protocolo binario eficiente, que es el más popular en producción).

ASN.1 = Gran papá

ASN.1 fue diseñado por personas de telecomunicaciones en los años 80 y es difícil de usar debido al soporte limitado de la biblioteca en comparación con los serializadores recientes que surgieron de la gente de CompSci. Hay dos variantes, la codificación DER (binaria) y la codificación PEM (ascii). Ambos son rápidos, pero DER es más rápido y tiene un tamaño más eficiente de los dos. De hecho, ASN.1 DER puede mantener fácilmente (y a veces superar) los serializadores que fueron diseñados 30 añosdespués de sí mismo, un testimonio de su diseño bien diseñado. Es muy compacto, más pequeño que Protocol Buffers y Thrift, solo superado por Avro. El problema es tener grandes bibliotecas que admitir y en este momento Bouncy Castle parece ser la mejor para C # / Java. ASN.1 es el rey en seguridad y sistemas criptográficos y no va a desaparecer, así que no se preocupe por las 'pruebas futuras'. Solo consigue una buena biblioteca ...

MessagePack = medio del paquete

No está mal, pero no es el más rápido, ni el más pequeño ni el mejor compatible. No hay razón de producción para elegirlo.

Común

Más allá de eso, son bastante similares. La mayoría son variantes del TLV: Type-Length-Valueprincipio básico .

Protocol Buffers (originado en Google), Avro (basado en Apache, utilizado en Hadoop), Thrift (originado en Facebook, ahora proyecto Apache) y ASN.1 (originado en Telecom) implican cierto nivel de generación de código donde primero expresa sus datos en un serializador específico del formato, entonces el "compilador" del serializador generará el código fuente para su idioma a través de la code-genfase. La fuente de la aplicación usa estas code-genclases para IO. Tenga en cuenta que ciertas implementaciones (por ejemplo: la biblioteca Avro de Microsoft o ProtoBuf.NET de Marc Gavel) le permiten decorar directamente sus objetos POCO / POJO de nivel de aplicación y luego la biblioteca usa directamente esas clases decoradas en lugar de cualquier clase de código gen. Hemos visto que esta oferta mejora el rendimiento, ya que elimina una etapa de copia de objetos (desde los campos POCO / POJO de nivel de aplicación hasta los campos de generación de código).

Algunos resultados y un proyecto en vivo para jugar

Este proyecto ( https://github.com/sidshetye/SerializersCompare ) compara serializadores importantes en el mundo C #. La gente de Java ya tiene algo similar .

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
fuente
3
ASN.1 también tiene BER (Reglas de codificación básicas), PER (Reglas de codificación empaquetadas) y XER (Reglas de codificación XML). DER es una variación de BER que se utiliza principalmente para la criptografía, ya que garantiza una codificación única para cada dato. Tanto BER como PER pueden ser más eficientes que DER. La mayoría de las bibliotecas procesan DER. Algunos no manejan todas las construcciones BER correctamente. Para aquellos que estén interesados ​​en obtener más información: luca.ntop.org/Teaching/Appunti/asn1.html
Joe Steele el
También tiene JER - Reglas de codificación de notación de objetos JavaScript. También puede definir sus propias reglas de codificación con ECN (notación de control de codificación). Buena lista de especificaciones con enlaces de descarga: oss.com/asn1/resources/standards-define-asn1.html
Dmitry
There are two variants, DER (binary) encoding and PEM (ascii) encoding. Tenga en cuenta que PEM es solo un dato binario codificado en base 64 dentro de los comentarios BEGIN END. Es posible que estos datos binarios se hayan generado utilizando la codificación DER, por lo que es extraño comparar PEM y DER.
RafalS
14

Además de la perspectiva del rendimiento, Uber evaluó recientemente varias de estas bibliotecas en su blog de ingeniería:

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

¿El ganador para ellos? MessagePack + zlib para compresión

Nuestro objetivo era encontrar la combinación de protocolo de codificación y algoritmo de compresión con el resultado más compacto a la velocidad más alta. Probamos el protocolo de codificación y las combinaciones de algoritmos de compresión en 2,219 viajes anonimizados pseudoaleatorios desde Uber New York City (colocados en un archivo de texto como JSON).

La lección aquí es que sus requisitos determinan qué biblioteca es la adecuada para usted. Para Uber, no podían usar un protocolo basado en IDL debido a la naturaleza sin esquema de la transmisión de mensajes que tienen. Esto eliminó un montón de opciones. También para ellos no solo entra en juego el tiempo de codificación / decodificación sin procesar, sino el tamaño de los datos en reposo.

Resultados de tamaño

Resultados de tamaño

Resultados de velocidad

ingrese la descripción de la imagen aquí

Avner
fuente
13

Lo más importante de ASN.1 es que está diseñado para especificación, no para la implementación. Por lo tanto, es muy bueno para ocultar / ignorar los detalles de implementación en cualquier lenguaje de programación "real".

Es el trabajo del compilador ASN.1 aplicar Reglas de codificación al archivo asn1 y generar a partir de ambos código ejecutable. Las Reglas de codificación pueden darse en la notación de codificación (ECN) o pueden ser una de las estandarizadas como BER / DER, PER, XER / EXER. Es decir, ASN.1 son los Tipos y Estructuras, las Reglas de codificación definen la codificación en el cable y, por último, pero no menos importante, el Compilador la transfiere a su lenguaje de programación.

Los compiladores gratuitos admiten C, C ++, C #, Java y Erlang, que yo sepa. Los compiladores comerciales (muy caros y con patentes / licencias) son muy versátiles, generalmente actualizados y admiten a veces incluso más idiomas, pero pueden ver sus sitios (OSS Nokalva, Marben, etc.).

Es sorprendentemente fácil especificar una interfaz entre partes de culturas de programación totalmente diferentes (por ejemplo, personas "integradas" y "granjeros de servidores") utilizando estas técnicas: un archivo asn.1, la regla de codificación, por ejemplo, BER y, por ejemplo, un diagrama de interacción UML . No se preocupe cómo se implementa, ¡deje que todos usen "lo suyo"! Para mí ha funcionado muy bien. Por cierto: en el sitio de OSS Nokalva puede encontrar al menos dos libros gratuitos sobre ASN.1 (uno de Larmouth y el otro de Dubuisson).

En mi humilde opinión, la mayoría de los otros productos intentan ser solo otros generadores de trozos RPC, bombeando mucho aire al problema de la serialización. Bueno, si uno necesita eso, uno podría estar bien. Pero para mí, parecen reinvenciones de Sun-RPC (desde finales de los 80), pero, bueno, eso también funcionó bien.

njimko
fuente
7

Bono de Microsoft ( https://github.com/Microsoft/bond ) es muy impresionante con rendimiento, funcionalidades y documentación. Sin embargo, no es compatible con muchas plataformas de destino a partir de ahora (13 de febrero de 2015). Solo puedo suponer que es porque es muy nuevo. Actualmente es compatible con Python, C # y C ++. Lo está utilizando MS en todas partes. Lo intenté, para mí, como desarrollador de ac #, usar bond es mejor que usar protobuf, sin embargo, también he usado ahorro, el único problema que enfrenté fue con la documentación, tuve que probar muchas cosas para entender cómo se hacen las cosas.

Pocos recursos en Bond son los siguientes ( 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
fuente
5

Para el rendimiento, un punto de datos es el punto de referencia de jvm-serializers : son mensajes pequeños muy específicos, pero podrían ayudar si se encuentra en la plataforma Java. Creo que el rendimiento en general a menudo no será la diferencia más importante. Además: NUNCA tome las palabras de los autores como evangelio; muchos reclamos anunciados son falsos (el sitio msgpack, por ejemplo, tiene algunos reclamos dudosos; puede ser rápido, pero la información es muy incompleta, el caso de uso no es muy realista).

Una gran diferencia es si se debe usar un esquema (PB, Thrift al menos; Avro puede ser opcional; ASN.1 Creo que también; MsgPack, no necesariamente).

Además: en mi opinión, es bueno poder usar un diseño modular en capas; es decir, la capa RPC no debe dictar el formato de datos, la serialización. Lamentablemente, la mayoría de los candidatos los agrupan estrechamente.

Finalmente, al elegir el formato de datos, hoy en día el rendimiento no impide el uso de formatos de texto. Hay analizadores JSON increíblemente rápidos (y analizadores xml de transmisión bastante rápida); y cuando se considera la interoperabilidad de los lenguajes de script y la facilidad de uso, los formatos y protocolos binarios pueden no ser la mejor opción.

StaxMan
fuente
Gracias por compartir experiencias, pero creo que todavía necesito el formato binario (tengo una gran cantidad de datos) y probablemente seguiré con Avro.
andreypopp
Sí, puede tener sentido entonces. Es posible que desee utilizar la compresión en cualquier caso, independientemente del formato que utilice (LZF es bueno ya que es muy rápido comprimir / descomprimir, en comparación con gzip / deflate).
StaxMan