Quais são as principais diferenças entre o Apache Thrift, os buffers de protocolo do Google, o MessagePack, ASN.1 e o Apache Avro?

124

Tudo isso fornece serialização binária, estruturas RPC e IDL. Estou interessado nas principais diferenças entre eles e as características (desempenho, facilidade de uso, suporte a linguagens de programação).

Se você conhece outras tecnologias semelhantes, mencione-as em uma resposta.

andreypopp
fonte
@ Zenikoder: Esse link não possui nenhuma informação para 2 dos 5 formatos consultados.
APENAS MINHA OPINIÃO correta
2
para aqueles que não conhecem a RPC - Remote Procedimento: Chamada, IDL - linguagem de definição de interface
garg10may

Respostas:

97

ASN.1 é um padrão ISO / ISE. Possui uma linguagem de origem muito legível e uma variedade de back-ends, tanto binários quanto legíveis por humanos. Sendo um padrão internacional (e antigo!), O idioma de origem é um pouco confuso (da mesma maneira que o Oceano Atlântico é um pouco úmido), mas é extremamente bem especificado e tem uma quantidade razoável de suporte . (Você provavelmente pode encontrar uma biblioteca ASN.1 para qualquer idioma que você nomear, se você se esforçar o suficiente, e se não houver boas bibliotecas de linguagem C disponíveis para serem usadas nas IFIs.) É, sendo uma linguagem padronizada, obsessivamente documentada e tem alguns bons tutoriais disponíveis também.

Thrift não é um padrão. Ele é originalmente do Facebook e foi posteriormente de código aberto e atualmente é um projeto Apache de nível superior. Não está bem documentado - especialmente os níveis de tutorial - e, a meu ver (reconhecidamente breve), não parece acrescentar nada que outros esforços anteriores ainda não fazem (e, em alguns casos, melhor). Para ser justo, ele possui um número impressionante de idiomas que suporta de imediato, incluindo alguns dos de maior destaque que não são populares. O IDL também é vagamente semelhante ao C.

Buffers de protocolo não é um padrão. É um produto do Google que está sendo lançado para a comunidade em geral. É um pouco limitado em termos de idiomas suportados de imediato (suporta apenas C ++, Python e Java), mas possui muito suporte de terceiros para outros idiomas (de qualidade altamente variável). O Google faz praticamente todo o seu trabalho usando Protocol Buffers, por isso é um protocolo testado em batalhas (embora não tão duro quanto o ASN.1. Ele possui uma documentação muito melhor do que a Thrift, mas, sendo um Produto do Google, é altamente provável que seja instável (no sentido de sempre mudar, não no sentido de não confiável) .O IDL também é semelhante ao C.

Todos os sistemas acima usam um esquema definido em algum tipo de IDL para gerar código para uma linguagem de destino que é usada na codificação e decodificação. Avro não. A digitação do Avro é dinâmica e seus dados de esquema são usados ​​em tempo de execução diretamente para codificar e decodificar (o que tem alguns custos óbvios no processamento, mas também alguns benefícios óbvios em relação às linguagens dinâmicas e uma falta de necessidade de tipos de marcação etc.) . Seu esquema usa JSON, o que facilita o gerenciamento do suporte ao Avro em um novo idioma se já houver uma biblioteca JSON. Novamente, como na maioria dos sistemas de descrição de protocolo para reinventar rodas, o Avro também não é padronizado.

Pessoalmente, apesar do meu relacionamento de amor / ódio com ele, eu provavelmente usaria o ASN.1 para a maioria dos propósitos de RPC e transmissão de mensagens, embora ele realmente não tenha uma pilha de RPC (você precisaria fazer um, mas os COI fazem isso simples o suficiente).

APENAS MINHA OPINIÃO correta
fonte
3
Obrigado pela explicação detalhada. Mas e quanto ao versionamento, ouvi dizer que o protobuf pode lidar com isso, o que acontece com outras bibliotecas e como é utilizável em comum? Além disso, parece que o Avro agora possui IDL com sintaxe do tipo C, além do JSON.
andreypopp
2
O ASN.1 suporta controle de versão manual através dos ...marcadores de extensão ou automático EXTENSIBILITY IMPLIEDno cabeçalho do módulo. Os buffers de protocolo, IIRC, oferecem suporte à versão manual. Não sei se ele suporta algo como extensibilidade implícita (e tenho preguiça de procurá-la). O Thrift também suporta algumas versões, mas, novamente, me parece um processo manual sem a extensibilidade implícita.
APENAS MINHA OPINIÃO correta
7
Para o registro, os Buffers de Protocolo sempre codificam explicitamente os campos por números e nunca é um erro no nível da biblioteca se houver campos extras, e os campos ausentes não são um erro se estiverem marcados como opcionais ou explícitos. Assim, todas as mensagens de buffers de protocolo possuem EXTENSIBILITY IMPLIED.
21812 Kevin Kathcart
por COI - você quer dizer inversão de controle? o que alguém usaria para a pilha RPC no PHP, algo como a extensão XML-RPC? ou alguém teria que escrever algo sozinho?
Stann
4
O Avro é mais flexível porque permite trabalhar dinamicamente em esquema definido ou gerar classes padrão. Pela minha experiência, é muito poderoso: sua força reside em seu rico conjunto de recursos, incluindo o gerador RPC (esse é um recurso comum do Thrift).
Paolo Maresca
38

Acabamos de fazer um estudo interno sobre serializadores, aqui estão alguns resultados (para minha referência futura também!)

Thrift = serialização + pilha RPC

A maior diferença é que o Thrift não é apenas um protocolo de serialização, é uma pilha RPC completa que é como uma pilha SOAP moderna. Portanto, após a serialização, os objetos podem (mas não são obrigatórios) ser enviados entre máquinas por TCP / IP. No SOAP, você começou com um documento WSDL que descreve completamente os serviços disponíveis (métodos remotos) e os argumentos / objetos esperados. Esses objetos foram enviados via XML. No Thrift, o arquivo .thrift descreve completamente os métodos disponíveis, os objetos de parâmetros esperados e os objetos são serializados por meio de um dos serializadores disponíveis (com Compact Protocolum protocolo binário eficiente, sendo o mais popular na produção).

ASN.1 = Grand Daddy

O ASN.1 foi projetado pelo pessoal de telecomunicações nos anos 80 e é difícil de usar devido ao suporte limitado à biblioteca, em comparação com os serializadores recentes que surgiram do pessoal do CompSci. Há duas variantes, codificação DER (binária) e codificação PEM (ascii). Ambos são rápidos, mas o DER é mais rápido e mais eficiente em tamanho dos dois. De fato, o ASN.1 DER pode facilmente acompanhar (e às vezes vencer) serializadores que foram projetados 30 anospor si só, um testemunho de seu design bem projetado. É muito compacto, menor que os Protocol Buffers e Thrift, vencidos apenas pela Avro. A questão é ter ótimas bibliotecas para oferecer suporte e, no momento, o Bouncy Castle parece ser o melhor para C # / Java. O ASN.1 é o rei em sistemas de segurança e criptografia e não vai desaparecer, portanto, não se preocupe com a 'prova futura'. Basta ter uma boa biblioteca ...

MessagePack = meio do pacote

Não é ruim, mas não é o mais rápido, nem o menor, nem o melhor suportado. Não há razão de produção para escolher.

Comum

Além disso, eles são bastante semelhantes. A maioria são variantes do TLV: Type-Length-Valueprincípio básico .

Buffers de protocolo (origem do Google), Avro (baseado no Apache, usado no Hadoop), Thrift (origem do Facebook, agora projeto Apache) e ASN.1 (origem da Telecom) envolvem algum nível de geração de código onde você expressa seus dados pela primeira vez em um serializador -específico, o "compilador" do serializador gerará o código-fonte para o seu idioma através da code-genfase. A fonte do seu aplicativo usa essas code-genclasses para E / S. Observe que certas implementações (por exemplo: biblioteca Avro da Microsoft ou ProtoBuf.NET de Marc Gavel) permitem decorar diretamente os objetos POCO / POJO no nível do aplicativo e, em seguida, a biblioteca usa diretamente essas classes decoradas em vez das classes de qualquer genitor de código. Vimos essa oferta melhorar o desempenho, pois elimina um estágio de cópia do objeto (dos campos POCO / POJO no nível do aplicativo aos campos de geração de código).

Alguns resultados e um projeto ao vivo para brincar

Este projeto ( https://github.com/sidshetye/SerializersCompare ) compara serializadores importantes no mundo C #. O pessoal do Java já tem algo parecido .

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
fonte
3
O ASN.1 também possui BER (Regras Básicas de Codificação), PER (Regras de Codificação em Pacote) e XER (Regras de Codificação XML). DER é uma variação do BER usada principalmente para criptografia, pois garante uma codificação exclusiva para cada dado. O BER e o PER podem ser mais eficientes que o DER. A maioria das bibliotecas processa o DER. Alguns não lidam com todas as construções do BER corretamente. Para aqueles que estão interessados em saber mais: luca.ntop.org/Teaching/Appunti/asn1.html
Joe Steele
Ele também possui regras de codificação JER - JavaScript Object Notation. Você também pode definir suas próprias regras de codificação com ECN (Notificação de controle de codificação). Boa lista de especificações com links para download: oss.com/asn1/resources/standards-define-asn1.html
Dmitry
There are two variants, DER (binary) encoding and PEM (ascii) encoding. Lembre-se de que o PEM é apenas um dado binário codificado em base 64 dentro dos comentários do BEGIN END. Esses dados binários podem ter sido gerados usando a codificação DER, por isso é estranho comparar o PEM e o DER.
RafalS
14

Além da perspectiva de desempenho, o Uber recentemente avaliou várias dessas bibliotecas em seu blog de engenharia:

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

O vencedor para eles? MessagePack + zlib para compactação

Nosso objetivo era encontrar a combinação de protocolo de codificação e algoritmo de compactação com o resultado mais compacto na velocidade mais alta. Testamos combinações de protocolo de codificação e algoritmo de compressão em 2.219 viagens anônimas pseudo-aleatórias da Uber de Nova York (inseridas em um arquivo de texto como JSON).

A lição aqui é que seus requisitos determinam qual biblioteca é ideal para você. Para o Uber, eles não podiam usar um protocolo baseado em IDL devido à natureza sem esquema da passagem de mensagens que possuem. Isso eliminou um monte de opções. Também para eles, não é apenas o tempo bruto de codificação / decodificação que entra em jogo, mas o tamanho dos dados em repouso.

Resultados de tamanho

Resultados de tamanho

Resultados de velocidade

insira a descrição da imagem aqui

Avner
fonte
13

A grande coisa sobre o ASN.1 é que ele é projetado para especificação não implementação. Portanto, é muito bom em ocultar / ignorar os detalhes da implementação em qualquer linguagem de programação "real".

É tarefa do compilador ASN.1 aplicar as regras de codificação ao arquivo asn1 e gerar a partir de ambos os códigos executáveis. As Regras de codificação podem ser fornecidas na Notificação de codificação (ECN) ou podem ser uma das padronizadas, como BER / DER, PER, XER / EXER. Ou seja, ASN.1 são os Tipos e Estruturas, as Regras de Codificação definem a codificação na conexão e, por último, mas não menos importante, o Compilador a transfere para sua linguagem de programação.

Os Compiladores gratuitos suportam C, C ++, C #, Java e Erlang, que eu saiba. Os compiladores comerciais (muito caros e com patentes / licenças) são muito versáteis, geralmente absolutamente atualizados e, às vezes, suportam ainda mais idiomas, mas veem seus sites (OSS Nokalva, Marben etc.).

É surpreendentemente fácil especificar uma interface entre partes de culturas de programação totalmente diferentes (por exemplo, pessoas "incorporadas" e "servidores de servidores") usando estas técnicas: um arquivo asn.1, a regra de codificação, por exemplo, BER e, por exemplo, um diagrama de interação UML . Não se preocupe como é implementado, deixe que todos usem "suas coisas"! Para mim, funcionou muito bem. Btw .: No site da OSS Nokalva, você pode encontrar pelo menos dois livros gratuitos para download sobre ASN.1 (um de Larmouth e outro de Dubuisson).

IMHO, a maioria dos outros produtos tenta apenas ser mais um outro gerador de stub de RPC, injetando muito ar na questão da serialização. Bem, se alguém precisar disso, pode estar bem. Mas para mim, elas parecem reinvenções do Sun-RPC (do final dos anos 80), mas, ei, isso funcionou bem também.

njimko
fonte
7

Bond da Microsoft ( https://github.com/Microsoft/bond ) é muito impressionante com desempenho, funcionalidades e documentação. No entanto, ele não suporta muitas plataformas de destino a partir de agora (13 de fevereiro de 2015). Só posso assumir que é porque é muito novo. Atualmente, ele suporta python, c # e c ++. Está sendo usado pela MS em todos os lugares. Eu tentei, para mim, como desenvolvedor AC # usando vínculo é melhor do que usar protobuf; no entanto, também usei economia, o único problema que enfrentei foi com a documentação, tive que tentar muitas coisas para entender como as coisas são feitas.

Poucos recursos no Bond são os seguintes ( 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
fonte
5

Para desempenho, um ponto de dados é o benchmark jvm-serializers - são pequenas mensagens bastante específicas, mas podem ajudar se você estiver na plataforma Java. Acho que o desempenho em geral geralmente não será a diferença mais importante. Além disso: NUNCA tome as palavras dos autores como evangelho; muitas declarações anunciadas são falsas (o site msgpack, por exemplo, tem algumas declarações duvidosas; pode ser rápido, mas as informações são muito incompletas, o caso de uso não é muito realista).

Uma grande diferença é se um esquema deve ser usado (PB, Thrift pelo menos; Avro pode ser opcional; ASN.1 também acho; MsgPack, não necessariamente).

Além disso: na minha opinião, é bom poder usar o design modular em camadas; isto é, a camada RPC não deve ditar o formato dos dados, a serialização. Infelizmente, a maioria dos candidatos os agrupa firmemente.

Finalmente, ao escolher o formato dos dados, hoje em dia o desempenho não impede o uso de formatos de texto. Existem analisadores JSON extremamente rápidos (e analisadores xml de streaming bastante rápidos); e ao considerar a interoperabilidade das linguagens de script e a facilidade de uso, os formatos e protocolos binários podem não ser a melhor opção.

StaxMan
fonte
Obrigado por compartilhar experiências, mas acho que ainda preciso de formato binário (tenho uma quantidade enorme de dados) e provavelmente continuarei com o Avro.
andreypopp
Sim, pode fazer sentido então. Você pode usar a compactação de qualquer forma, independentemente do formato a ser usado (o LZF é bom, pois é muito rápido compactar / descompactar, comparado ao gzip / deflate).
precisa saber é o seguinte