value Quais são as principais diferenças entre o Apache Thrift, o Google Protocol Buffers, o MessagePack, o ASN.1 e o Apache Avro?




using google protobuf (5)

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

Thrift = serialização + pilha RPC

A maior diferença é que Thrift não é apenas um protocolo de serialização, é uma pilha RPC completa que é como uma pilha SOAP moderna. Assim, após a serialização, os objetos poderiam (mas não obrigatórios) ser enviados entre as máquinas pelo 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 o Compact Protocol , um protocolo binário eficiente, sendo o mais popular na produção).

ASN.1 = pai grande

ASN.1 foi projetado por pessoas de telecomunicações nos anos 80 e é difícil de usar devido ao suporte limitado da biblioteca, em comparação com os serializadores recentes que surgiram de pessoal CompSci. Existem 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 termos de tamanho dos dois. Na verdade, o ASN.1 DER pode facilmente manter (e às vezes bater) serializadores que foram projetados 30 anos depois de si mesmo, uma prova de que é um projeto bem projetado. É muito compacto, menor que os Buffers de Protocolo e o Thrift, apenas vencidos pelo Avro. A questão é ter ótimas bibliotecas para dar suporte e agora o Bouncy Castle parece ser o melhor para C # / Java. O ASN.1 é o rei dos sistemas de segurança e criptografia e não vai desaparecer, então não se preocupe com a 'prova futura'. Apenas pegue uma boa biblioteca ...

MessagePack = meio da embalagem

Não é ruim, mas nem é o mais rápido, nem o menor nem o melhor suportado. Nenhuma razão de produção para escolhê-lo.

Comum

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

Buffers de protocolo (originado pelo Google), Avro (baseado em Apache, usado no Hadoop), Thrift (originado do Facebook, agora projeto Apache) e ASN.1 (originado por Telecom) envolvem algum nível de geração de código onde você primeiro expressa seus dados em um serializador -específico formato, então o "compilador" serializador irá gerar código-fonte para o seu idioma através da fase de code-gen . Em seguida, a origem do seu aplicativo usa essas classes de code-gen para o pedido de veiculação. Note que certas implementações (por exemplo: a biblioteca Avro da Microsoft ou o ProtoBuf.NET de Marc Gavel) permitem que você decore diretamente seus objetos POCO / POJO no nível do aplicativo e, em seguida, a biblioteca usa diretamente essas classes decoradas em vez das classes de qualquer genebra. Vimos que essa oferta oferece um desempenho aprimorado, já que elimina um estágio de cópia de objeto (dos campos POCO / POJO no nível do aplicativo para campos de código-gen).

Alguns resultados e um projeto ao vivo para jogar

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!)

Todos eles fornecem serialização binária, frameworks RPC e IDL. Estou interessado em diferenças fundamentais entre eles e características (desempenho, facilidade de uso, suporte a linguagens de programação).

Se você conhece alguma outra tecnologia similar, por favor mencione em uma resposta.


O Bond da Microsoft ( https://github.com/Microsoft/bond ) é muito impressionante com desempenho, funcionalidades e documentação. No entanto, não suporta muitas plataformas de destino a partir de agora (13 de fevereiro de 2015). Eu só posso supor que é porque é muito novo. atualmente suporta python, c # e c ++. Está sendo usado pela MS em todos os lugares. Eu tentei, para mim, como um desenvolvedor # usando o bond é melhor do que usar o protobuf, mas eu usei o thrift também, o único problema que enfrentei foi com a documentação, eu 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 )


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

É o trabalho do ASN.1-Compiler para aplicar 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 em EnCoding Notation (ECN) ou podem ser uma das padronizadas, como BER / DER, PER, XER / EXER. Isso é o ASN.1 são os Tipos e Estruturas, as Regras de Codificação definem a codificação de fio e, por último, mas não menos importante, o Compilador o transfere para sua linguagem de programação.

Os compiladores gratuitos suportam C, C ++, C #, Java e Erlang, até onde eu sei. Os compiladores comerciais (muito caros e patenteados / licenciados) são muito versáteis, geralmente absolutamente atualizados e suportam algumas vezes até mesmo mais idiomas, mas veja 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 "criadores de servidores") usando essas técnicas: um arquivo asn.1, a regra de Codificação, por exemplo, BER e um Diagrama de Interação UML. . Não se preocupe como isso é implementado, deixe todo mundo usar "a coisa deles"! Para mim, funcionou muito bem. Btw .: No site da OSS Nokalva, você pode encontrar pelo menos dois livros gratuitos sobre ASN.1 (um de Larmouth e outro de Dubuisson).

A maioria dos outros produtos da IMHO tenta ser apenas um outro gerador de tocos RPC, bombeando muito ar para a 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.


ASN.1 é um padrão ISO / ISE. Tem uma linguagem fonte muito legível e uma variedade de back-ends, tanto binário quanto legível por humanos. Sendo uma norma internacional (e antiga), a língua de partida é um pouco banhada na cozinha (quase da mesma forma que o Oceano Atlântico é um pouco molhado), mas é extremamente bem especificada e tem uma quantidade decente de apoio. . (Provavelmente você pode encontrar uma biblioteca ASN.1 para qualquer idioma que você nomear, se você cavar o suficiente, e se não houver boas bibliotecas de linguagem C disponíveis que você pode usar em FFIs.) É, sendo uma linguagem padronizada, obsessivamente documentada e Tem alguns bons tutoriais disponíveis também.

Thrift não é um padrão. É originalmente do Facebook e mais tarde foi open-source e atualmente é um projeto Apache de nível superior. Não está bem documentado - especialmente os níveis de tutorial - e meu olhar (reconhecidamente breve) não parece acrescentar nada que outros esforços anteriores já não tenham feito (e, em alguns casos, melhores). Para ser justo, tem um número bastante impressionante de idiomas que suporta fora da caixa, incluindo alguns dos que não são de grande repercussão. O IDL também é vagamente semelhante ao C.

Protocol Buffers 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 fora da caixa (suporta apenas C ++, Python e Java), mas tem muito suporte de terceiros para outras linguagens (de qualidade altamente variável). O Google faz praticamente todo o seu trabalho usando Protocol Buffers, por isso é um protocolo testado em batalha e endurecido pela batalha (embora não tão duro quanto o ASN.1. Ele tem uma documentação muito melhor do que o Thrift, mas, sendo um Produto do Google, é altamente provável que seja instável (no sentido de sempre em mudança, não no sentido de não confiável) .O IDL é também C-like.

Todos os sistemas acima usam um esquema definido em algum tipo de IDL para gerar código para uma linguagem de destino que é então 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 a linguagens dinâmicas e a falta de necessidade de tipos de tags, etc.) . Seu esquema usa JSON, o que torna o suporte ao Avro em um novo idioma um pouco mais fácil de gerenciar, se já houver uma biblioteca JSON. Novamente, como ocorre com a maioria dos sistemas de descrição de protocolo que reinventam as 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 não tenha uma pilha de RPCs (você teria que fazer um, mas IOCs fazem isso simples o suficiente).


Para desempenho, um ponto de dados é o benchmark jvm-serializers - são mensagens pequenas e bem específicas, mas podem ajudar se você estiver na plataforma Java. Eu acho que o desempenho em geral não será a diferença mais importante. Também: NUNCA tome as palavras dos autores como evangelho; muitas alegações anunciadas são falsas (o site msgpack, por exemplo, tem algumas afirmações duvidosas; pode ser rápido, mas a informação é muito incompleta, 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 eu acho também; MsgPack, não necessariamente).

Além disso: na minha opinião, é bom poder usar o design modular em camadas; ou seja, a camada RPC não deve ditar o formato de dados, a serialização. Infelizmente, a maioria dos candidatos faz isso muito bem.

Finalmente, ao escolher o formato de dados, a performance atual não impede o uso de formatos textuais. Há analisadores de JSON muito rápidos (e analisadores xml muito rápidos); e ao considerar a interoperabilidade a partir de linguagens de script e facilidade de uso, os formatos e protocolos binários podem não ser a melhor escolha.