Udostępnij za pośrednictwem


Zagadnienia dotyczące kodowania komunikatów

Wiele aplikacji w chmurze używa komunikatów asynchronicznych do wymiany informacji między składnikami systemu. Ważnym aspektem obsługi komunikatów jest format używany do kodowania danych ładunku. Po wybraniu technologii obsługi komunikatów następnym krokiem jest zdefiniowanie sposobu kodowania komunikatów. Dostępnych jest wiele opcji, ale odpowiedni wybór zależy od przypadku użycia.

W tym artykule opisano niektóre zagadnienia.

Wymagania dotyczące wymiany komunikatów

Wymiana komunikatów między producentem a konsumentem wymaga:

  • Kształt lub struktura definiująca ładunek komunikatu.
  • Format kodowania reprezentujący ładunek.
  • Biblioteki serializacji do odczytu i zapisu zakodowanego ładunku.

Producent komunikatu definiuje kształt komunikatu na podstawie logiki biznesowej i informacji, które chce wysłać do odbiorców. Aby określić strukturę kształtu, podziel informacje na odrębne lub powiązane tematy (pola). Zdecyduj, jakie są cechy wartości dla tych pól. Rozważmy: Jaki jest najbardziej wydajny typ danych? Czy ładunek zawsze będzie miał pewne pola? Czy ładunek będzie miał jeden rekord lub wielokrotny zestaw wartości?

Następnie wybierz format kodowania w zależności od potrzeb. Niektóre czynniki obejmują możliwość tworzenia wysoce ustrukturyzowanych danych, jeśli są one potrzebne, czas potrzebny na kodowanie i przesyłanie komunikatu oraz możliwość analizowania ładunku. W zależności od formatu kodowania wybierz bibliotekę serializacji, która jest dobrze obsługiwana.

Odbiorca wiadomości musi być świadomy tych decyzji, aby wiedzieć, jak odczytywać komunikaty przychodzące.

Aby przenieść komunikaty, producent serializuje komunikat do formatu kodowania. Na końcu odbioru konsument deserializuje ładunek, aby używać danych. W ten sposób obie jednostki współdzielą model i tak długo, jak kształt nie ulegnie zmianie, obsługa komunikatów będzie kontynuowana bez problemów. Po zmianie kontraktu format kodowania powinien być w stanie obsługiwać zmianę bez przerywania konsumenta.

Niektóre formaty kodowania, takie jak JSON, opisują się samodzielnie, co oznacza, że można je analizować bez odwoływania się do schematu. Jednak takie formaty zwykle dają większe komunikaty. W przypadku innych formatów dane mogą nie być analizowane tak łatwo, ale komunikaty są kompaktowe. W tym artykule wyróżniono niektóre czynniki, które mogą pomóc w wyborze formatu.

Zagadnienia dotyczące formatu kodowania

Format kodowania definiuje sposób, w jaki zestaw danych strukturalnych jest reprezentowany jako bajty. Typ komunikatu może mieć wpływ na wybór formatu. Komunikaty związane z transakcjami biznesowymi najprawdopodobniej będą zawierać wysoce ustrukturyzowane dane. Ponadto możesz pobrać go później na potrzeby inspekcji. W przypadku strumienia zdarzeń możesz chcieć odczytać sekwencję rekordów tak szybko, jak to możliwe i zapisać je do analizy statystycznej.

Poniżej przedstawiono kilka kwestii, które należy wziąć pod uwagę podczas wybierania formatu kodowania.

Czytelność człowieka

Kodowanie komunikatów może być szeroko podzielone na formaty tekstowe i binarne.

W przypadku kodowania opartego na tekście ładunek komunikatu jest w postaci zwykłego tekstu i dlatego może być sprawdzany przez osobę bez używania żadnych bibliotek kodu. Formaty czytelne dla człowieka są odpowiednie dla danych archiwalnych. Ponadto, ponieważ człowiek może odczytać ładunek, formaty oparte na tekście są łatwiejsze do debugowania i wysyłania do dzienników w celu rozwiązywania problemów z błędami.

Wadą jest to, że ładunek jest zwykle większy. Typowy format tekstowy to JSON.

Szyfrowanie

Jeśli w komunikatach znajdują się poufne dane, należy rozważyć, czy te komunikaty powinny być szyfrowane w całości zgodnie z opisem w tych wskazówkach dotyczących szyfrowania danych usługi Azure Service Bus magazynowanych. Alternatywnie, jeśli tylko niektóre pola muszą być zaszyfrowane i wolisz zmniejszyć koszty chmury, rozważ użycie biblioteki, takiej jak NServiceBus .

Rozmiar kodowania

Rozmiar komunikatu ma wpływ na wydajność we/wy sieci przez przewody. Formaty binarne są bardziej kompaktowe niż formaty tekstowe. Formaty binarne wymagają bibliotek serializacji/deserializacji. Nie można odczytać ładunku, chyba że został zdekodowany.

Użyj formatu binarnego, jeśli chcesz szybciej zmniejszyć zużycie przewodu i przesyłać komunikaty. Ta kategoria formatu jest zalecana w scenariuszach, w których problemem jest przepustowość magazynu lub sieci. Opcje formatów binarnych obejmują Apache Avro, Bufory protokołu Google (protobuf), MessagePack i Concise Binary Object Representation (CBOR). Zalety i wady tych formatów opisano w tej sekcji.

Wadą jest to, że ładunek nie jest czytelny dla człowieka. Większość formatów binarnych używa złożonych systemów, które mogą być kosztowne do utrzymania. Ponadto potrzebują wyspecjalizowanych bibliotek do dekodowania, które mogą nie być obsługiwane, jeśli chcesz pobrać dane archiwalne.

Opis ładunku

Ładunek komunikatu jest dostarczany jako sekwencja bajtów. Aby przeanalizować tę sekwencję, użytkownik musi mieć dostęp do metadanych opisujących pola danych w ładunku. Istnieją dwa główne podejścia do przechowywania i dystrybucji metadanych:

Oznakowane metadane. W niektórych kodowaniu, zwłaszcza w formacie JSON, pola są oznaczone typem danych i identyfikatorem w treści komunikatu. Te formaty opisują się samodzielnie, ponieważ można je analizować w słowniku wartości bez odwoływania się do schematu. Jednym ze sposobów zrozumienia pól przez konsumenta jest wykonywanie zapytań o oczekiwane wartości. Na przykład producent wysyła ładunek w formacie JSON. Odbiorca analizuje dane JSON w słowniku i sprawdza istnienie pól, aby zrozumieć ładunek. Innym sposobem jest zastosowanie przez konsumenta modelu danych współużytkowanego przez producenta. Jeśli na przykład używasz statycznie typizowanego języka, wiele bibliotek serializacji JSON może przeanalizować ciąg JSON w klasie typizowanej.

Schemat. Schemat formalnie definiuje strukturę i pola danych komunikatu. W tym modelu producent i konsument mają umowę za pomocą dobrze zdefiniowanego schematu. Schemat może definiować typy danych, wymagane/opcjonalne pola, informacje o wersji i strukturę ładunku. Producent wysyła ładunek zgodnie ze schematem modułu zapisywania. Odbiorca odbiera ładunek, stosując schemat czytnika. Komunikat jest serializowany/deserializowany przy użyciu bibliotek specyficznych dla kodowania. Istnieją dwa sposoby dystrybucji schematów:

  • Zapisz schemat jako preambuł lub nagłówek w komunikacie, ale oddzielony od ładunku.

  • Przechowuj schemat zewnętrznie.

Niektóre formaty kodowania definiują schemat i używają narzędzi, które generują klasy na podstawie schematu. Producent i konsument używają tych klas i bibliotek do serializacji i deserializacji ładunku. Biblioteki zapewniają również kontrole zgodności między modułem zapisywania i schematem czytnika. Zarówno protobuf, jak i Apache Avro są zgodne z tym podejściem. Kluczową różnicą jest to, że protobuf ma niezależną od języka definicję schematu, ale Avro używa kompaktowego kodu JSON. Inną różnicą jest sposób, w jaki oba formaty zapewniają sprawdzanie zgodności między schematami czytnika i modułu zapisywania.

Innym sposobem przechowywania schematu zewnętrznie w rejestrze schematów. Komunikat zawiera odwołanie do schematu i ładunku. Producent wysyła identyfikator schematu w komunikacie, a użytkownik pobiera schemat, określając ten identyfikator z magazynu zewnętrznego. Obie strony używają biblioteki specyficznej dla formatu do odczytywania i zapisywania komunikatów. Oprócz przechowywania schematu rejestr może zapewnić sprawdzanie zgodności, aby upewnić się, że umowa między producentem a konsumentem nie jest uszkodzona, ponieważ schemat ewoluuje.

Przed wybraniem podejścia zdecyduj, co jest ważniejsze: rozmiar transferu danych lub możliwość analizowania zarchiwizowanych danych później.

Przechowywanie schematu wraz z ładunkiem daje większy rozmiar kodowania i jest preferowane dla sporadycznych komunikatów. Wybierz to podejście, jeśli przenoszenie mniejszych fragmentów bajtów ma kluczowe znaczenie lub oczekujesz sekwencji rekordów. Koszt utrzymania zewnętrznego magazynu schematów może być wysoki.

Jeśli jednak dekodowanie ładunku na żądanie jest ważniejsze niż rozmiar, w tym schemat z ładunkiem lub podejście do oznakowanych metadanych gwarantuje dekodowanie później. Może wystąpić znaczny wzrost rozmiaru komunikatów i może mieć wpływ na koszt magazynu.

Przechowywanie wersji schematu

W miarę zmiany wymagań biznesowych oczekuje się, że kształt zmieni się, a schemat będzie się zmieniał. Przechowywanie wersji umożliwia producentowi wskazanie aktualizacji schematu, które mogą obejmować nowe funkcje. Istnieją dwa aspekty przechowywania wersji:

  • Użytkownik powinien mieć świadomość zmian.

    Jednym ze sposobów jest sprawdzenie wszystkich pól przez odbiorcę w celu określenia, czy schemat został zmieniony. Innym sposobem jest opublikowanie przez producenta numeru wersji schematu z komunikatem. Gdy schemat ewoluuje, producent zwiększa wersję.

  • Zmiany nie mogą wpływać na logikę biznesową konsumentów ani nie naruszać jej logiki biznesowej.

    Załóżmy, że pole zostało dodane do istniejącego schematu. Jeśli użytkownicy korzystający z nowej wersji otrzymają ładunek zgodnie ze starą wersją, ich logika może ulec awarii, jeśli nie będą mogli pominąć braku nowego pola. Biorąc pod uwagę odwrotny przypadek, załóżmy, że pole zostało usunięte w nowym schemacie. Użytkownicy używający starego schematu mogą nie być w stanie odczytać danych.

    Formaty kodowania, takie jak Avro, oferują możliwość definiowania wartości domyślnych. W poprzednim przykładzie, jeśli pole zostanie dodane z wartością domyślną, brakujące pole zostanie wypełnione wartością domyślną. Inne formaty, takie jak protobuf, zapewniają podobne funkcje za pośrednictwem wymaganych i opcjonalnych pól.

Struktura ładunku

Rozważ sposób rozmieszczania danych w ładunku. Czy jest to sekwencja rekordów, czy odrębny pojedynczy ładunek? Struktura ładunku można podzielić na jeden z następujących modeli:

  • Tablica/słownik/wartość: definiuje wpisy, które przechowują wartości w jednej lub wielowymiarowej tablicy. Wpisy mają unikatowe pary klucz-wartość. Można ją rozszerzyć, aby reprezentować złożone struktury. Niektóre przykłady to: JSON, Apache Avro i MessagePack.

    Ten układ jest odpowiedni, jeśli komunikaty są kodowane indywidualnie przy użyciu różnych schematów. Jeśli masz wiele rekordów, ładunek może być nadmiernie nadmiarowy, powodując przelocenie ładunku.

  • Dane tabelaryczne: informacje są podzielone na wiersze i kolumny. Każda kolumna wskazuje pole lub temat informacji, a każdy wiersz zawiera wartości dla tych pól. Ten układ jest wydajny w przypadku powtarzającego się zestawu informacji, takich jak dane szeregów czasowych.

    CSV jest jednym z najprostszych formatów opartych na tekście. Przedstawia dane jako sekwencję rekordów ze wspólnym nagłówkiem. W przypadku kodowania binarnego apache Avro ma preambułę podobną do nagłówka CSV, ale generuje kompaktowy rozmiar kodowania.

Obsługa bibliotek

Rozważ użycie dobrze znanych formatów w modelu zastrzeżonym.

Dobrze znane formaty są obsługiwane przez biblioteki, które są powszechnie obsługiwane przez społeczność. W przypadku wyspecjalizowanych formatów potrzebne są określone biblioteki. Logika biznesowa może potrzebować obejścia niektórych opcji projektowania interfejsu API udostępnianych przez biblioteki.

W przypadku formatu opartego na schemacie wybierz bibliotekę kodowania, która umożliwia sprawdzanie zgodności między schematem czytnika i modułu zapisywania. Niektóre biblioteki kodowania, takie jak Apache Avro, oczekują, że odbiorca określi zarówno składnik zapisywania, jak i schemat czytnika przed deserializacji komunikatu. Ta kontrola zapewnia, że odbiorca zna wersje schematu.

Współdziałanie

Wybór formatów może zależeć od konkretnego obciążenia lub ekosystemu technologii.

Na przykład:

  • Usługa Azure Stream Analytics ma natywną obsługę plików JSON, CSV i Avro. W przypadku korzystania z usługi Stream Analytics warto wybrać jeden z tych formatów, jeśli to możliwe. Jeśli nie, możesz podać niestandardowy deserializator, ale spowoduje to dodanie dodatkowej złożoności do rozwiązania.

  • JSON to standardowy format wymiany dla interfejsów API REST PROTOKOŁU HTTP. Jeśli aplikacja odbiera ładunki JSON od klientów, a następnie umieszcza je w kolejce komunikatów na potrzeby przetwarzania asynchronicznego, warto użyć formatu JSON do obsługi komunikatów, a nie ponownie zakodować je w innym formacie.

Są to tylko dwa przykłady zagadnień dotyczących współdziałania. Ogólnie rzecz biorąc, standardowe formaty będą bardziej współdziałać niż formaty niestandardowe. W opcjach opartych na tekście kod JSON jest jednym z najbardziej współdziałalnych.

Opcje formatowania kodowania

Oto kilka popularnych formatów kodowania. Przed wybraniem formatu należy uwzględnić zagadnienia.

JSON

JSON to otwarty standard (IETF RFC8259). Jest to format oparty na tekście, który jest zgodny z modelem tablicy/słownika/wartości.

Kod JSON może służyć do tagowania metadanych i można przeanalizować ładunek bez schematu. Kod JSON obsługuje opcję określania pól opcjonalnych, które ułatwiają zgodność z poprzednimi wersjami i do przodu.

Największą zaletą jest to, że jest powszechnie dostępna. Jest to najbardziej współdziałanie i domyślny format kodowania dla wielu usług obsługi komunikatów.

Będąc formatem opartym na tekście, nie jest wydajny za pośrednictwem przewodu, a nie idealnym wyborem w przypadkach, gdy magazyn jest problemem. Jeśli zwracasz buforowane elementy bezpośrednio do klienta za pośrednictwem protokołu HTTP, przechowywanie danych JSON może obniżyć koszt deserializacji z innego formatu, a następnie serializowania do formatu JSON.

Użyj formatu JSON dla komunikatów z pojedynczym rekordem lub dla sekwencji komunikatów, w których każdy komunikat ma inny schemat. Unikaj używania formatu JSON dla sekwencji rekordów, takich jak dane szeregów czasowych.

Istnieją inne odmiany kodu JSON, takie jak binarny kod JSON (BSON), który jest kodowaniem binarnym dopasowanym do pracy z bazą danych MongoDB.

Wartości rozdzielane przecinkami (CSV)

CSV to format tabelaryczny oparty na tekście. Nagłówek tabeli wskazuje pola. Jest to preferowany wybór, w którym komunikat zawiera zestaw rekordów.

Wadą jest brak standaryzacji. Istnieje wiele sposobów wyrażania separatorów, nagłówków i pustych pól.

Bufory protokołu (protobuf)

Bufory protokołu (lub protobuf) to format serializacji, który używa silnie typizowanych plików definicji do definiowania schematów w parach klucz/wartość. Te pliki definicji są następnie kompilowane do klas specyficznych dla języka, które są używane do serializacji i deserializacji komunikatów.

Komunikat zawiera skompresowany mały ładunek binarny, co skutkuje szybszym transferem. Wadą jest to, że ładunek nie jest czytelny dla człowieka. Ponadto ze względu na to, że schemat jest zewnętrzny, nie zaleca się pobierania zarchiwizowanych danych.

Apache Avro

Apache Avro to binarny format serializacji, który używa pliku definicji podobnego do protobuf, ale nie ma kroku kompilacji. Zamiast tego serializowane dane zawsze zawierają preambuły schematu.

Preambuła może zawierać nagłówek lub identyfikator schematu. Ze względu na mniejszy rozmiar kodowania firma Avro jest zalecana w przypadku danych przesyłanych strumieniowo. Ponadto, ponieważ ma nagłówek, który ma zastosowanie do zestawu rekordów, jest dobrym wyborem dla danych tabelarycznych.

MessagePack

MessagePack to binarny format serializacji zaprojektowany z myślą o kompaktowym rozwiązaniu do przesyłania przez sieć. Nie obejmuje schematów komunikatów ani kontroli typów komunikatów. Ten format nie jest zalecany w przypadku magazynu zbiorczego.

CBOR

Zwięzła reprezentacja obiektu binarnego (CBOR) to format binarny, który oferuje mały rozmiar kodowania. Zaletą CBOR over MessagePack jest to, że jest zgodna z programem IETF w RFC7049.

Następne kroki