Freigeben über


Bewährte Methoden für die Nachrichtencodierung

Viele Cloudanwendungen verwenden asynchrone Nachrichten, um Informationen zwischen Komponenten des Systems auszutauschen. Ein wichtiger Aspekt des Messaging ist das Format, das zum Codieren der Nutzlastdaten verwendet wird. Nachdem Sie eine Messagingtechnologie ausgewählt haben, besteht der nächste Schritt darin, zu definieren, wie die Nachrichten codiert werden. Es gibt viele Optionen, aber die richtige Wahl hängt von Ihrem Anwendungsfall ab.

In diesem Artikel werden einige der Überlegungen beschrieben.

Anforderungen für den Nachrichtenaustausch

Ein Nachrichtenaustausch zwischen einem Produzenten und einem Verbraucher erfordert:

  • Ein Shape oder eine Struktur, die die Nutzlast der Nachricht definiert.
  • Ein Codierungsformat, das die Nutzlast darstellt.
  • Serialisierungsbibliotheken zum Lesen und Schreiben der codierten Nutzlast.

Der Produzent der Nachricht definiert das Nachrichten-Shape basierend auf der Geschäftslogik und den Informationen, die sie an die Verbraucher senden möchte. Um das Shape zu strukturieren, teilen Sie die Informationen in einzelne oder verwandte Themen (oder Felder) auf. Legen Sie die Merkmale der Werte für diese Felder fest. Berücksichtigen Sie die folgenden Fragen.

  • Was ist der effizienteste Datentyp?
  • Verfügt die Nutzlast immer über bestimmte Felder?
  • Verfügt die Nutzlast über einen einzelnen Datensatz oder einen wiederholten Wertesatz?

Wählen Sie dann je nach Ihren Anforderungen ein Codierungsformat aus. Zu den spezifischen Faktoren gehören die Möglichkeit, hochstrukturierte Daten zu erstellen, wenn Sie sie benötigen, die Zeit zum Codieren und Übertragen der Nachricht sowie die Möglichkeit, die Nutzlast zu analysieren. Wählen Sie dann ein Codierungsformat aus, das Ihren Anforderungen entspricht.

Der Verbraucher muss diese Entscheidungen verstehen, um eingehende Nachrichten ordnungsgemäß zu lesen.

Um Nachrichten zu übertragen, serialisiert der Produzent die Nachricht in ein Codierungsformat. Auf der Empfangsseite deserialisiert der Consumer die Nutzdaten, um auf die Daten zuzugreifen. Dieser Prozess stellt sicher, dass beide Entitäten dasselbe Modell gemeinsam nutzen. Solange die Form unverändert bleibt, wird die Kommunikation ohne Probleme fortgeführt. Wenn sich der Vertrag ändert, sollte das Codierungsformat in der Lage sein, die Änderung zu verarbeiten, ohne den Verbraucher zu unterbrechen.

Einige Codierungsformate wie JSON sind selbstbeschreibungen, was bedeutet, dass sie analysiert werden können, ohne auf ein Schema zu verweisen. Diese Formate erzeugen jedoch häufig größere Nachrichten. Andere Formate analysieren daten möglicherweise nicht so einfach, führen aber zu kompakteren Nachrichten. In diesem Artikel werden wichtige Faktoren beschrieben, mit denen Sie das richtige Format auswählen können.

Überlegungen zum Codierungsformat

Das Codierungsformat definiert, wie eine Gruppe strukturierter Daten als Bytes dargestellt wird. Der Typ der Nachricht kann die Auswahl des Formats beeinflussen. Nachrichten im Zusammenhang mit Geschäftstransaktionen enthalten höchstwahrscheinlich hochgradig strukturierte Daten. Außerdem können Sie die strukturierten Daten später für Überwachungszwecke abrufen. Bei einem Datenstrom von Ereignissen sollten Sie eine Abfolge von Datensätzen so schnell wie möglich lesen und für statistische Analysen speichern.

Berücksichtigen Sie die folgenden Faktoren, wenn Sie ein Codierungsformat auswählen.

Menschliche Lesbarkeit

Die Nachrichtencodierung kann allgemein in textbasierte und binäre Formate unterteilt werden.

Bei textbasierter Codierung befindet sich die Nachrichtennutzlast im Nur-Text-Format, sodass eine Person sie ohne Codebibliotheken prüfen kann. Dieser Ansatz erleichtert das Lesen und Verstehen von Daten. Lesbare Formate eignen sich für Archivdaten. Da die Nutzdaten von einem Menschen gelesen werden können, lassen sich textbasierte Formate leichter debuggen und für die Problembehandlung an Protokolle senden.

Der Nachteil der textbasierten Codierung besteht darin, dass die Nutzlast tendenziell größer ist. Die Nutzlastgröße kann oft durch einen Minimierungsprozess reduziert werden, solange sie bei Bedarf zur menschlichen Lesbarkeit umgekehrt werden kann. Gängige textbasierte Formate sind JSON und YAML.

Verschlüsselung

Wenn vertrauliche Daten in den Nachrichten vorhanden sind, überlegen Sie, ob diese Nachrichten vollständig verschlüsselt werden sollen. Wenn nur bestimmte Felder verschlüsselt werden müssen und Sie die Cloudkosten lieber reduzieren möchten, sollten Sie eine Bibliothek wie NServiceBus verwenden.

Codierungsgröße

Die Nachrichtengröße wirkt sich auf die Netzwerkeingabe-/Ausgabeleistung über das Netzwerk aus. Binärformate sind kompakter als textbasierte Formate. Binäre Formate erfordern Serialisierungs- und Deserialisierungsbibliotheken. Die Nutzlast kann nur gelesen werden, wenn sie entschlüsselt ist.

Verwenden Sie ein Binärformat, wenn Sie den Drahtbedarf reduzieren und Nachrichten schneller übertragen möchten. Diese Formatkategorie wird in Szenarien empfohlen, in denen Speicher- oder Netzwerkbandbreite ein Problem darstellt. Optionen für Binäre Formate sind Apache Avro, Google Protocol Buffers (Protobuf), MessagePack und Concise Binary Object Representation (CBOR). Die Vor- und Nachteile dieser Formate werden später in "Auswahlmöglichkeiten für Codierungsformate" beschrieben.

Der Nachteil des Binärformats besteht darin, dass die Nutzlast nicht lesbar ist. Die meisten Binärformate verwenden komplexe Systeme, die für die Wartung kostspielig sein können. Außerdem benötigen sie spezielle Bibliotheken zum Decodieren, was möglicherweise nicht unterstützt wird, wenn Sie Archivierungsdaten abrufen möchten.

Bei nichtbinären Formaten entfernt ein Minimierungsprozess unnötige Leerzeichen und Zeichen, während die Einhaltung der Spezifikation des Formats beibehalten wird. Dieser Ansatz trägt dazu bei, die Codierungsgröße zu reduzieren, ohne die Struktur zu ändern. Bewerten Sie die Funktionen Ihres Encoders, um die Minimierung zur Standardeinstellung zu machen. Beispiel: JsonSerializerOptions.WriteIndented aus dem System.Text.Json.JsonSerializer von .NET steuert die automatische Minimierung beim Erstellen von JSON-Text.

Grundlegendes zur Nutzlast

Eine Nachrichtennutzlast wird als Sequenz von Bytes empfangen. Um diese Sequenz zu analysieren, muss der Consumer Zugriff auf Metadaten haben, die die Datenfelder in der Nutzlast beschreiben. Die beiden wichtigsten Ansätze zum Speichern und Verteilen von Metadaten sind:

Markierte Metadaten. In einigen Codierungsformaten, insbesondere JSON, werden Felder mit dem Datentyp und bezeichner im Textkörper der Nachricht markiert. Diese Formate sind selbstbeschreibend, da sie in ein Wörterbuch mit Werten geparst werden können, ohne auf ein Schema zu verweisen. Eine Möglichkeit für den Verbraucher, die Felder zu verstehen, besteht darin, nach erwarteten Werten abzufragen. Der Producer sendet beispielsweise eine Nutzlast in JSON. Der Consumer analysiert den JSON-Code in ein Wörterbuch und prüft auf das Vorhandensein Feldern, um die Nutzlast zu verstehen. Eine andere Möglichkeit besteht darin, dass der Verbraucher ein Datenmodell anwendet, das der Hersteller teilt. Wenn Sie beispielsweise eine statisch eingegebene Sprache verwenden, können viele JSON-Serialisierungsbibliotheken eine JSON-Zeichenfolge in eine typierte Klasse analysieren.

Schema Ein Schema definiert formell die Struktur- und Datenfelder einer Nachricht. In diesem Modell haben der Hersteller und der Verbraucher einen Vertrag über ein gut definiertes Schema. Das Schema kann die Datentypen, die erforderlichen oder optionalen Felder, Versionsinformationen und die Struktur der Nutzlast definieren. Der Producer sendet die Nutzdaten gemäß dem Writer-Schema. Der Consumer empfängt die Nutzlast durch Anwenden eines Reader-Schemas. Die Nachricht wird mithilfe der codierungsspezifischen Bibliotheken serialisiert und deserialisiert. Schemas können auf zwei Arten verteilt werden:

  • Speichern Sie das Schema als Präambel oder Kopfzeile in der Nachricht, aber getrennt von der Nutzlast.

  • Speichern Sie das Schema extern.

Einige Codierungsformate definieren das Schema und verwenden Tools, die Klassen aus dem Schema generieren. Der Produzent und Konsument verwenden diese Klassen und Bibliotheken, um die Nutzlast zu serialisieren und zu deserialisieren. Die Bibliotheken bieten außerdem Kompatibilitätsüberprüfungen zwischen dem Schreiber- und Leseschema. Sowohl protobuf als auch Apache Avro folgen diesem Ansatz. Der Hauptunterschied besteht darin, dass protobuf über eine sprachunabhängige Schemadefinition verfügt und Avro kompakte JSON verwendet. Ein weiterer Unterschied besteht darin, dass beide Formate Kompatibilitätsprüfungen zwischen Reader- und Writer-Schemas bereitstellen.

Eine weitere Möglichkeit zum externen Speichern des Schemas befindet sich in einer Schemaregistrierung. Die Nachricht enthält einen Verweis auf das Schema und die Nutzlast. Der Produzent sendet die Schema-ID in der Nachricht. Der Consumer ruft das Schema ab, indem er diesen Bezeichner aus einem externen Speicher angibt. Beide Parteien verwenden eine formatspezifische Bibliothek zum Lesen und Schreiben von Nachrichten. Zusätzlich zum Speichern des Schemas kann eine Registrierung Kompatibilitätsprüfungen bereitstellen, um sicherzustellen, dass der Vertrag zwischen Produzent und Verbraucher nicht unterbrochen wird, wenn sich das Schema weiterentwickelt.

Bevor Sie einen Ansatz auswählen, entscheiden Sie, ob die Größe der Übertragungsdaten oder die Möglichkeit, die archivierten Daten später zu analysieren, wichtiger ist.

Das Speichern des Schemas zusammen mit der Nutzlast erzeugt eine größere Codierungsgröße und eignet sich ideal für zeitweilige Nachrichten. Wählen Sie diesen Ansatz aus, wenn das Übertragen kleinerer Byteabschnitte von entscheidender Bedeutung ist oder Sie eine Abfolge von Datensätzen erwarten. Die Kosten für die Wartung eines externen Schemaspeichers können hoch sein.

Wenn jedoch die On-Demand-Decodierung der Nutzlast wichtiger ist als die Größe, garantiert das Einbeziehen des Schemas mit der Nutzlast oder des getaggten Metadatenansatzes die anschließende Decodierung. Es kann eine erhebliche Zunahme der Nachrichtengröße geben, die sich auf die Speicherkosten auswirkt.

Versionsverwaltung des Schemas

Wenn sich die Geschäftsanforderungen ändern, wird erwartet, dass sich das Shape ändert, und das Schema wird sich weiterentwickeln. Mit der Versionsverwaltung kann der Produzent Schemaupdates angeben, die möglicherweise neue Features enthalten. Die Versionsverwaltung weist zwei wichtige Aspekte auf:

  • Der Verbraucher sollte die Änderungen nachverfolgen und verstehen.

    Eine Möglichkeit besteht darin, dass der Verbraucher alle Felder überprüft, um festzustellen, ob sich das Schema geändert hat. Eine weitere Möglichkeit besteht darin, dass der Produzent eine Schemaversionsnummer mit der Nachricht veröffentlicht. Wenn sich das Schema weiterentwickelt, erhöht der Produzent die Version.

  • Änderungen dürfen die Geschäftslogik von Verbrauchern nicht beeinflussen oder unterbrechen.

    Angenommen, ein Feld wird einem vorhandenen Schema hinzugefügt. Wenn Verbraucher, die die neue Version verwenden, eine Nutzlast gemäß der alten Version erhalten, kann ihre Logik gestört werden, wenn sie das Fehlen des neuen Felds nicht ignorieren können. Betrachten Sie nun das gegenteilige Szenario. Wenn ein Feld im neuen Schema entfernt wird, können Verbraucher, die das alte Schema verwenden, die Daten möglicherweise nicht lesen.

    Codierungsformate wie Avro bieten die Möglichkeit, Standardwerte zu definieren. Wenn im vorherigen Beispiel das Feld mit einem Standardwert hinzugefügt wird, wird das fehlende Feld mit dem Standardwert aufgefüllt. Andere Formate wie protobuf bieten ähnliche Funktionen über erforderliche und optionale Felder.

Nutzlaststruktur

Überlegen Sie, ob die Daten in der Nutzlast als Abfolge von Datensätzen oder als einzelne diskrete Nutzlast strukturiert sind. Die Nutzlaststruktur kann in einem der folgenden Modelle kategorisiert werden:

  • Array/Wörterbuch/Wert: Definiert Einträge, die Werte in ein- oder mehrdimensionalen Arrays halten. Einträge weisen eindeutige Schlüssel-Wert-Paare auf. Das Modell kann erweitert werden, um komplexe Strukturen darzustellen. Einige Beispiele sind JSON, Apache Avro und MessagePack.

    Dieses Layout eignet sich, wenn Nachrichten einzeln mit unterschiedlichen Schemas codiert werden. Wenn Sie über mehrere Datensätze verfügen, kann die Nutzlast übermäßig redundant sein. Diese Redundanz kann dazu führen, dass die Nutzlast aufgebläht wird.

  • Tabellendaten: Informationen werden in Zeilen und Spalten unterteilt. Jede Spalte gibt ein Feld oder den Betreff der Informationen an, und jede Zeile enthält Werte für diese Felder. Dieses Layout ist effizient für einen wiederholten Satz von Informationen, z. B. Zeitreihendaten.

    Comma-Separated Values (CSV) ist eines der einfachsten textbasierten Formate. Es stellt Daten als Abfolge von Datensätzen mit einem allgemeinen Header dar. Bei binärer Codierung verfügt Apache Avro über eine Präambel, die einem CSV-Header ähnelt, aber eine kompaktere Codierungsgröße generiert.

Bibliotheksunterstützung

Sie sollten bekannte Formate anstelle eines proprietären Modells verwenden. Bekannte Formate werden durch Bibliotheken unterstützt, die von der Community allgemein anerkannt sind. Mit spezialisierten Formaten benötigen Sie bestimmte Bibliotheken. Ihre Geschäftslogik muss möglicherweise einige der api-Designoptionen umgehen, die von den Bibliotheken bereitgestellt werden.

Wählen Sie für ein schemabasiertes Format eine Codierungsbibliothek aus, die Kompatibilitätsprüfungen zwischen dem Reader- und Writer-Schema vorgibt. Bestimmte Codierungsbibliotheken, z. B. Apache Avro, erwarten, dass der Verbraucher sowohl das Schreibschema als auch das Leseschema vor dem Deserialisieren der Nachricht angibt. Diese Überprüfung stellt sicher, dass der Verbraucher die Schemaversionen kennt.

Interoperabilität

Ihre Auswahl an Formaten hängt möglicherweise von der spezifischen Workload oder dem Technologieökosystem ab.

Zum Beispiel:

  • Azure Stream Analytics verfügt über systemeigene Unterstützung für JSON, CSV und Avro. Wenn Ihre Workload Stream Analytics verwendet, ist es sinnvoll, eines dieser Formate auszuwählen.

  • JSON ist ein Standardmäßiges Austauschformat für HTTP-REST-APIs. Wenn Ihre Anwendung JSON-Nutzlasten von Clients empfängt und sie dann zur asynchronen Verarbeitung in eine Nachrichtenwarteschlange einordnet, ist es möglicherweise sinnvoll, JSON für das Messaging zu verwenden, anstatt sie in einem anderen Format erneut zu codieren.

Dies sind nur zwei Beispiele für Interoperabilitätsüberlegungen. Standardisierte Formate sind im Allgemeinen interoperabler als benutzerdefinierte Formate. In textbasierten Optionen ist JSON einer der interoperabelsten.

Auswahlmöglichkeiten für Codierungsformate

Die folgenden gängigen Codierungsformate werden für die Datendarstellung und -übertragung verwendet. Berücksichtigen Sie die Überlegungen, bevor Sie ein Format auswählen.

JSON

JSON ist ein offener Standard mit dem von der Internet Engineering Task Force (IETF) in RFC 8259 definierten Format. JSON ist ein textbasiertes Format, das dem Array-/Wörterbuch/Wertmodell folgt.

JSON kann zum Kategorisieren von Metadaten verwendet werden, und Sie können die Nutzlast ohne Schema analysieren. JSON unterstützt die Option zum Angeben optionaler Felder, die sowohl bei der Vorwärts- als auch der Abwärtskompatibilität hilfreich sind.

Der größte Vorteil besteht darin, dass es universell verfügbar ist. JSON ist das interoperableste Codierungsformat und die Standardeinstellung für viele Messagingdienste.

Da JSON ein textbasiertes Format ist, ist es nicht effizient über das Kabel und nicht ideal, wenn der Speicher ein Problem darstellt. Verwenden Sie minifizierungstechniken, wenn möglich. Wenn Sie zwischengespeicherte Elemente direkt über HTTP an einen Client zurückgeben, kann das Speichern von JSON die Kosten sparen, die bei der Deserialisierung aus einem anderen Format und der anschließenden Serialisierung in JSON entstehen.

Verwenden Sie JSON für Einzeldatensatznachrichten oder für eine Abfolge von Nachrichten, in denen jede Nachricht ein anderes Schema aufweist. Vermeiden Sie JSON für eine Abfolge von Datensätzen, z. B. für Daten aus Zeitreihen.

Es gibt weitere Variationen von JSON, z. B. binäres JSON (BSON). BSON ist eine binäre Codierung, die an der Arbeit mit MongoDB ausgerichtet ist.

CSV-Datei

CSV ist ein textbasiertes tabellarisches Format. Die Kopfzeile der Tabelle gibt die Felder an. CSV eignet sich gut für Nachrichten, die eine Gruppe von Datensätzen enthalten.

Der Nachteil von CSV ist ein Mangel an Standardisierung. Es gibt mehrere Möglichkeiten zum Ausdrücken von Trennzeichen, Kopfzeilen und leeren Feldern.

Protokollpuffer

Protokollpuffer (oder Protobuf) ist ein Serialisierungsformat, das stark typierte Definitionsdateien verwendet, um Schemas in Schlüssel-Wert-Paaren zu definieren. Diese Definitionsdateien werden dann zu sprachspezifischen Klassen kompiliert, die zum Serialisieren und Deserialisieren von Nachrichten verwendet werden.

Die Nachricht enthält eine kleine, komprimierte binäre Nutzlast, was zu einer schnelleren Datenübertragung führt. Der Nachteil ist, dass die Nutzlast nicht menschlich lesbar ist. Da das Schema extern gespeichert ist, eignet sich dieses Format nicht ideal für Szenarien, in denen Archivierte Daten abgerufen werden müssen.

Apache Avro

Apache Avro ist ein binäres Serialisierungsformat, das eine Definitionsdatei verwendet, die dem Protobuf ähnelt, jedoch ohne Kompilierungsschritt. Stattdessen enthalten serialisierte Daten immer eine Schema-Präambel.

Die Präambel kann den Header oder einen Schemabezeichner enthalten. Aufgrund der geringeren Codierungsgröße wird Avro für Streamingdaten empfohlen. Da sie auch über eine Kopfzeile verfügt, die für eine Gruppe von Datensätzen gilt, eignet sie sich gut für tabellarische Daten.

Apache-Parkett

Apache Parquet ist ein spaltenbasiertes Speicherdateiformat, das in der Regel Apache Hadoop und verwandten Datenverarbeitungsframeworks zugeordnet ist.

Apache Parquet unterstützt die Datenkomprimierung und verfügt über begrenzte Funktionen für die Schema-Evolution. Dieses Format wird in der Regel verwendet, wenn andere Big Data-Technologien in Ihrer Workload das Format für die Erstellung oder Nutzung von Daten benötigen.

MessagePack

MessagePack ist ein binäres Serialisierungsformat, das für die Übertragung über das Kabel kompakt ist. MessagePack enthält keine Schemadefinition und Typüberprüfung. Dieses Format wird für den Massenspeicher nicht empfohlen.

CBOR

CBOR (Specification) ist ein Binärformat, das eine kleine Codierungsgröße bereitstellt. Der Vorteil der Verwendung von CBOR im Vergleich zu MessagePack ist seine Einhaltung des IETF-Standards gemäß RFC7049.

Nächste Schritte