Jakie są kluczowe różnice między Apache Thrift, Google Protocol Buffers, MessagePack, ASN.1 i Apache Avro?

124

Wszystkie zapewniają serializację binarną, struktury RPC i IDL. Interesują mnie kluczowe różnice między nimi oraz ich cechy (wydajność, łatwość obsługi, obsługa języków programowania).

Jeśli znasz inne podobne technologie, podaj je w odpowiedzi.

andreypopp
źródło
@Zenikoder: Ten link nie zawiera żadnych informacji dla 2 z 5 zapytanych formatów.
TYLKO MOJA poprawna OPINIA
2
dla tych, którzy nie znają RPC - Remote Prodecure Call, IDL - Interface Definition language
garg10 może

Odpowiedzi:

97

ASN.1 to standard ISO / ISE. Ma bardzo czytelny język źródłowy i różnorodne zaplecze, zarówno binarne, jak i czytelne dla człowieka. Będąc międzynarodowym standardem (i to starym!), Język źródłowy jest nieco zlewozmywakowy (mniej więcej w taki sam sposób, w jaki Ocean Atlantycki jest trochę mokry), ale jest bardzo dobrze określony i ma przyzwoitą ilość wsparcia . (Prawdopodobnie możesz znaleźć bibliotekę ASN.1 dla dowolnego języka, który nazwiesz, jeśli będziesz wystarczająco mocno kopać, a jeśli nie, są dostępne dobre biblioteki języka C, których możesz używać w FFI.) Jest to język ustandaryzowany, obsesyjnie udokumentowany i ma również kilka dobrych samouczków.

Oszczędność nie jest standardem. Pochodzi z Facebooka, a później był open-source i obecnie jest projektem Apache najwyższego poziomu. Nie jest to dobrze udokumentowane - zwłaszcza poziomy samouczków - i moim (wprawdzie krótkim) spojrzeniem nie wydaje się dodawać niczego, czego inne poprzednie wysiłki jeszcze nie robią (aw niektórych przypadkach lepsze). Aby być uczciwym, ma dość imponującą liczbę języków, które obsługuje po wyjęciu z pudełka, w tym kilka bardziej znanych języków spoza głównego nurtu. IDL jest również nieco podobny do C.

Bufory protokołów nie są standardem. Jest to produkt Google, który jest udostępniany szerszej społeczności. Jest nieco ograniczony pod względem języków obsługiwanych po wyjęciu z pudełka (obsługuje tylko C ++, Python i Java), ale ma wiele wsparcia dla innych języków (o bardzo zmiennej jakości). Google prawie całą swoją pracę wykonuje przy użyciu buforów protokołów, więc jest to sprawdzony w boju, zahartowany w boju protokół (choć nie tak zahartowany w boju jak ASN.1. Ma znacznie lepszą dokumentację niż Thrift, ale będąc Produkt Google, jest wysoce prawdopodobne, że będzie niestabilny (w sensie ciągłych zmian, a nie zawodności). IDL jest również podobny do C.

Wszystkie powyższe systemy używają schematu zdefiniowanego w pewnego rodzaju IDL do generowania kodu dla języka docelowego, który jest następnie używany do kodowania i dekodowania. Avro tego nie robi. Pisanie Avro jest dynamiczne, a jego dane schematu są używane bezpośrednio w czasie wykonywania zarówno do kodowania, jak i dekodowania (co ma pewne oczywiste koszty przetwarzania, ale także pewne oczywiste korzyści w porównaniu z dynamicznymi językami i brakiem potrzeby znakowania typów itp.) . Jego schemat wykorzystuje JSON, co sprawia, że ​​obsługa Avro w nowym języku jest nieco łatwiejsza w zarządzaniu, jeśli istnieje już biblioteka JSON. Ponownie, podobnie jak w przypadku większości systemów opisu protokołów opracowanych na nowo, Avro również nie jest znormalizowany.

Osobiście, pomimo mojej relacji miłości / nienawiści, prawdopodobnie użyłbym ASN.1 do większości celów RPC i transmisji wiadomości, chociaż tak naprawdę nie ma stosu RPC (musiałbyś go stworzyć, ale MKOl to robi wystarczająco proste).

TYLKO MOJA poprawna OPINIA
źródło
3
Dzięki za szczegółowe wyjaśnienie. Ale co z wersjonowaniem, słyszałem, że protobuf sobie z tym poradzi, a co z innymi bibliotekami i jak to jest wspólne? Wygląda też na to, że Avro ma teraz IDL ze składnią podobną do C, oprócz JSON.
andreypopp
2
ASN.1 obsługuje ręczne wersjonowanie za pomocą ...znaczników rozszerzeń lub automatyczne EXTENSIBILITY IMPLIEDw nagłówku modułu. Bufory protokołów, IIRC, obsługują ręczne przechowywanie wersji. Nie wiem, czy obsługuje coś takiego, jak domniemana rozszerzalność (i jestem zbyt leniwy, aby to sprawdzić). Oszczędność obsługuje również niektóre wersje, ale ponownie wydaje mi się, że jest to proces ręczny bez domniemanej rozszerzalności.
TYLKO MOJA poprawna OPINIA
7
W przypadku rekordu bufory protokołów zawsze jawnie kodują pola według liczb i nigdy nie jest błędem na poziomie biblioteki, jeśli istnieją dodatkowe pola, a brakujące pola nie są błędem, jeśli są oznaczone jako opcjonalne lub jawne. Tak więc wszystkie komunikaty buforów protokołów mają EXTENSIBILITY IMPLIED.
Kevin Cathcart,
przez MKOl - czy masz na myśli odwrócenie kontroli? Czego można użyć dla stosu RPC w PHP, czegoś w rodzaju rozszerzenia XML-RPC? czy trzeba by coś napisać samodzielnie?
Stann
4
Avro jest bardziej elastyczny, ponieważ pozwala albo dynamicznie pracować na zdefiniowanym schemacie, albo generować standardowe klasy. Z mojego doświadczenia wynika, że ​​jest bardzo potężny: jego siła tkwi w bogatym zestawie funkcji, w tym generatorze RPC (jest to cecha wspólna w przypadku Thrift).
Paolo Maresca
38

Właśnie przeprowadziliśmy wewnętrzne badanie dotyczące serializatorów, oto kilka wyników (również do mojego przyszłego odniesienia!)

Thrift = serializacja + stos RPC

Największą różnicą jest to, że Thrift to nie tylko protokół serializacji, to pełny stos RPC, który przypomina współczesny stos SOAP. Zatem po serializacji obiekty mogą (ale nie wymagane) być przesyłane między maszynami przez TCP / IP. W SOAP rozpoczęto od dokumentu WSDL, który w pełni opisuje dostępne usługi (metody zdalne) i oczekiwane argumenty / obiekty. Obiekty te zostały przesłane przez XML. W Thrift plik .thrift w pełni opisuje dostępne metody, oczekiwane obiekty parametrów, a obiekty są serializowane za pomocą jednego z dostępnych serializatorów (z Compact Protocolwydajnym protokołem binarnym, najbardziej popularnym w produkcji).

ASN.1 = dziadek

ASN.1 został zaprojektowany przez ludzi z branży telekomunikacyjnej w latach 80-tych i jest niewygodny w użyciu z powodu ograniczonej obsługi bibliotek w porównaniu do ostatnich serializatorów, które pojawiły się w CompSci. Istnieją dwa warianty, kodowanie DER (binarne) i kodowanie PEM (ascii). Oba są szybkie, ale DER jest szybszy i bardziej efektywny pod względem rozmiaru. W rzeczywistości ASN.1 DER może z łatwością nadążyć (a czasem pokonać) serializatory, które zostały zaprojektowane od 30 latsama w sobie jest świadectwem dobrze zaprojektowanego projektu. Jest bardzo kompaktowy, mniejszy niż bufory protokołu i oszczędność, pokonany tylko przez Avro. Problemem jest posiadanie wspaniałych bibliotek do obsługi i obecnie Bouncy Castle wydaje się być najlepszym rozwiązaniem dla C # / Java. ASN.1 jest królem zabezpieczeń i systemów kryptograficznych i nie zniknie, więc nie martw się o „przyszłe zabezpieczenia”. Po prostu zdobądź dobrą bibliotekę ...

MessagePack = środek paczki

Nie jest zły, ale nie jest ani najszybszy, ani najmniejszy, ani najlepiej obsługiwany. Nie ma powodu produkcyjnego, aby go wybrać.

Wspólny

Poza tym są dość podobne. Większość z nich to warianty podstawowej TLV: Type-Length-Valuezasady.

Bufory protokołów (pochodzące z Google), Avro (oparte na Apache, używane w Hadoop), Thrift (pochodzące z Facebooka, obecnie projekt Apache) i ASN.1 (pochodzące z Telecom) - wszystkie obejmują pewien poziom generowania kodu, w którym najpierw wyrażasz swoje dane w serializatorze -specyficznym formacie, wtedy "kompilator" serializatora wygeneruje kod źródłowy dla twojego języka poprzez code-genfazę. Twoje źródło aplikacji następnie używa tych code-genklas na potrzeby IO. Zwróć uwagę, że niektóre implementacje (np. Biblioteka Avro firmy Microsoft lub ProtoBuf.NET Marca Gavela) umożliwiają bezpośrednie dekorowanie obiektów POCO / POJO na poziomie aplikacji, a następnie biblioteka bezpośrednio używa tych ozdobionych klas zamiast klas kodu genowego. Widzieliśmy, że oferuje to zwiększenie wydajności, ponieważ eliminuje etap kopiowania obiektu (z pól POCO / POJO na poziomie aplikacji do pól generowania kodu).

Niektóre wyniki i projekt na żywo do zabawy

Ten projekt ( https://github.com/sidshetye/SerializersCompare ) porównuje ważne serializatory w świecie C #. Ludzie z Java mają już coś podobnego .

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
źródło
3
ASN.1 ma również BER (podstawowe reguły kodowania), PER (reguły upakowanego kodowania) i XER (reguły kodowania XML). DER to odmiana BER, która jest używana głównie do kryptografii, ponieważ gwarantuje unikalne kodowanie dla każdej danej. Zarówno BER, jak i PER mogą być bardziej wydajne niż DER. Większość bibliotek przetwarza DER. Niektóre nie obsługują poprawnie wszystkich konstrukcji BER. Dla tych, którzy chcą dowiedzieć się więcej: luca.ntop.org/Teaching/Appunti/asn1.html
Joe Steele
Posiada również JER - reguły kodowania notacji obiektów JavaScript. Możesz także zdefiniować własne reguły kodowania za pomocą ECN (Encoding Control Notation). Dobra lista specyfikacji z linkami do pobrania: oss.com/asn1/resources/standards-define-asn1.html
Dmitry
There are two variants, DER (binary) encoding and PEM (ascii) encoding. Należy pamiętać, że PEM to po prostu dane binarne zakodowane w formacie base-64 wewnątrz komentarzy BEGIN END. Te dane binarne mogły zostać wygenerowane przy użyciu kodowania DER, więc dziwne jest porównywanie PEM i DER.
RafałS
14

Dodając perspektywę wydajności, Uber niedawno ocenił kilka z tych bibliotek na swoim blogu inżynieryjnym:

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

Zwycięzca dla nich? MessagePack + zlib do kompresji

Naszym celem było znalezienie kombinacji protokołu kodowania i algorytmu kompresji z najbardziej kompaktowym wynikiem przy największej szybkości. Przetestowaliśmy kombinacje protokołów kodowania i algorytmów kompresji podczas 2219 pseudolosowych anonimowych podróży z Ubera w Nowym Jorku (umieszczonych w pliku tekstowym jako JSON).

Lekcja jest taka, że ​​to Twoje wymagania decydują o wyborze odpowiedniej biblioteki. W przypadku Ubera nie mogli używać protokołu opartego na IDL ze względu na pozbawiony schematu charakter przekazywania wiadomości. To wyeliminowało wiele opcji. Również dla nich liczy się nie tylko czas surowego kodowania / dekodowania, ale także rozmiar danych w spoczynku.

Wyniki rozmiaru

Wyniki rozmiaru

Wyniki prędkości

wprowadź opis obrazu tutaj

Avner
źródło
13

Jedną wielką rzeczą w ASN.1 jest to, że jest on zaprojektowany dla specyfikacji, a nie implementacji. Dlatego bardzo dobrze ukrywa / ignoruje szczegóły implementacji w każdym „prawdziwym” języku programowania.

Zadaniem kompilatora ASN.1 jest zastosowanie reguł kodowania do pliku asn1 i wygenerowanie z obu z nich kodu wykonywalnego. Reguły kodowania mogą być podane w notacji kodowania (ECN) lub mogą być jedną z ustandaryzowanych, takich jak BER / DER, PER, XER / EXER. Czyli ASN.1 to Typy i Struktury, Reguły Kodowania definiują kodowanie na kablu, a co nie mniej ważne, Kompilator przenosi je do twojego języka programowania.

Darmowe kompilatory obsługują C, C ++, C #, Java i Erlang zgodnie z moją wiedzą. Komercyjne kompilatory (bardzo drogie i oparte na patentach / licencjach) są bardzo wszechstronne, zwykle absolutnie aktualne i obsługują czasami nawet więcej języków, ale zobacz ich strony (OSS Nokalva, Marben itp.).

Zaskakująco łatwo jest określić interfejs między stronami o zupełnie różnych kulturach programowania (np. "Osadzeni" ludzie i "rolnicy serwerów") przy użyciu tych technik: plik asn.1, zasada kodowania np. BER i np. Diagram interakcji UML . Nie martw się, jak to jest zaimplementowane, niech wszyscy używają „swoich rzeczy”! U mnie to działa bardzo dobrze. Przy okazji: Na stronie OSS Nokalva można znaleźć co najmniej dwie darmowe książki o ASN.1 (jedną autorstwa Larmouth, a drugą Dubuissona).

Większość innych produktów IMHO stara się być tylko kolejnymi generatorami odgałęzień RPC, pompując dużo powietrza do problemu serializacji. Cóż, jeśli tego potrzeba, może być dobrze. Ale dla mnie wyglądają jak nowe wynalazki Sun-RPC (z końca lat 80-tych), ale hej, to też działało dobrze.

njimko
źródło
7

Microsoft Bond ( https://github.com/Microsoft/bond ) jest imponujący pod względem wydajności, funkcjonalności i dokumentacji. Jednak obecnie nie obsługuje wielu platform docelowych (13 lutego 2015 r.). Mogę tylko przypuszczać, że to dlatego, że jest bardzo nowy. obecnie obsługuje Python, C # i C ++. Jest używany przez stwardnienie rozsiane wszędzie. Wypróbowałem to, dla mnie jako programisty ac # używanie bond jest lepsze niż używanie protobuf, jednak użyłem też oszczędności, jedyny problem, z jakim miałem do czynienia, dotyczył dokumentacji, musiałem spróbować wielu rzeczy, aby zrozumieć, jak się wszystko dzieje.

Niewiele zasobów na temat Bond jest następujących ( 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
źródło
5

Jeśli chodzi o wydajność, jednym punktem danych jest test porównawczy jvm-serializerów - są to dość specyficzne, małe komunikaty, ale mogą pomóc, jeśli używasz platformy Java. Myślę, że generalnie wydajność często nie będzie najważniejszą różnicą. Ponadto: NIGDY nie traktuj słów autorów jako ewangelii; wiele reklamowanych twierdzeń jest fałszywych (na przykład witryna msgpack zawiera podejrzane twierdzenia; może być szybka, ale informacje są bardzo pobieżne, a przypadek użycia niezbyt realistyczny).

Jedną dużą różnicą jest to, czy należy użyć schematu (PB, przynajmniej Thrift; Avro może być opcjonalny; myślę, że ASN.1 również; MsgPack, niekoniecznie).

Poza tym: moim zdaniem dobrze jest móc korzystać z warstwowej, modułowej konstrukcji; to znaczy warstwa RPC nie powinna dyktować formatu danych, serializacji. Niestety większość kandydatów ściśle je łączy.

Wreszcie, przy wyborze formatu danych, dzisiejsza wydajność nie wyklucza stosowania formatów tekstowych. Istnieją niesamowicie szybkie parsery JSON (i całkiem szybkie parsery strumieniowe XML); a biorąc pod uwagę interoperacyjność z języków skryptowych i łatwość użycia, formaty i protokoły binarne mogą nie być najlepszym wyborem.

StaxMan
źródło
Dziękuję za podzielenie się doświadczeniami, ale myślę, że nadal potrzebuję formatu binarnego (mam naprawdę ogromną ilość danych) i prawdopodobnie pozostanę przy Avro.
andreypopp
W takim razie może mieć sens. Możesz chcieć użyć kompresji w dowolnym tempie, niezależnie od używanego formatu (LZF jest przyjemny, ponieważ kompresowanie / dekompresowanie jest bardzo szybkie w porównaniu do gzip / deflate).
StaxMan