protocol-buffers - value - using google protobuf




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

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.


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.


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

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.


Somando-se à 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 compressão com o resultado mais compacto na velocidade mais alta. Nós testamos combinações de algoritmos de compressão e protocolo de codificação em 2.219 viagens anônimas pseudo-aleatórias da Uber New York City (colocadas em um arquivo de texto como JSON).

A lição aqui é que seus requisitos determinam qual biblioteca é a certa para você. Para o Uber, eles não puderam 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 velocidade