Von Azure Web PubSub unterstütztes protobuf-WebSocket-Unterprotokoll

In diesem Dokument wird das Unterprotokoll protobuf.webpubsub.azure.v1 beschrieben.

Wenn ein Client dieses Unterprotokoll verwendet, wird erwartet, dass es sich sowohl bei den ausgehenden als auch den eingehenden Dataframes um Protokollpuffernutzlasten (protobuf) handelt.

Überblick

Das Unterprotokoll protobuf.webpubsub.azure.v1 ermöglicht es den Clients, direkt Veröffentlichen-Abonnieren-Vorgänge (Publish-Subscribe, PubSub) anstelle eines Roundtrips zum Upstreamserver durchzuführen. Die WebSocket-Verbindung mit dem Unterprotokoll protobuf.webpubsub.azure.v1 wird auch „PubSub-WebSocket-Client“ genannt.

In JavaScript können Sie beispielsweise einen PubSub-WebSocket-Client mit dem protobuf-Unterprotokoll erstellen, indem Sie Folgendes verwenden:

// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');

Für einen einfachen WebSocket-Client verfügt der Server über die erforderliche Rolle für die Behandlung von Clientereignissen. Eine einfache WebSocket-Verbindung löst beim Senden von Nachrichten immer ein message-Ereignis aus, und die Verarbeitung von Nachrichten und andere Vorgänge werden immer serverseitig ausgeführt. Mithilfe des Unterprotokolls protobuf.webpubsub.azure.v1 kann ein autorisierter Client unter Verwendung von Joinanforderungen einer Gruppe beitreten und Nachrichten mit Veröffentlichungsanforderungen direkt in einer Gruppe veröffentlichen. Der Client kann mithilfe von Ereignisanforderungen Nachrichten auch an verschiedene Upstreamereignishandler weiterleiten, um das Ereignis anzupassen, zu dem die Nachricht gehört.

Hinweis

Derzeit unterstützt der Web PubSub-Dienst nur proto3.

Berechtigungen

Ein PubSub WebSocket-Client kann nur auf anderen Clients veröffentlicht werden, wenn er autorisiert ist. Der roles dem Client zugewiesene Legt die Berechtigungen fest, die dem Client gewährt werden:

Role Berechtigung
Nicht angegeben Der Client kann Ereignisanforderungen senden.
webpubsub.joinLeaveGroup Der Client kann einer beliebigen Gruppe beitreten/diese verlassen.
webpubsub.sendToGroup Der Client kann Nachrichten in einer beliebigen Gruppe veröffentlichen.
webpubsub.joinLeaveGroup.<group> Der Client kann der Gruppe <group>beitreten/verlassen.
webpubsub.sendToGroup.<group> Der Client kann Nachrichten in der Gruppe <group>veröffentlichen.

Der Server kann Clientberechtigungen dynamisch über REST-APIs oder Server-SDKs erteilen oder widerrufen.

Requests

Alle Anforderungsnachrichten entsprechen dem folgenden protobuf-Format:

syntax = "proto3";

import "google/protobuf/any.proto";

message UpstreamMessage {
    oneof message {
        SendToGroupMessage send_to_group_message = 1;
        EventMessage event_message = 5;
        JoinGroupMessage join_group_message = 6;
        LeaveGroupMessage leave_group_message = 7;
    }

    message SendToGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
        MessageData data = 3;
    }

    message EventMessage {
        string event = 1;
        MessageData data = 2;
        optional uint64 ack_id = 3;
    }
    
    message JoinGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
    }

    message LeaveGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
    }
}

message MessageData {
    oneof data {
        string text_data = 1;
        bytes binary_data = 2;
        google.protobuf.Any protobuf_data = 3;
    }
}

Gruppen beitreten

Format:

Legen Sie join_group_message.group auf den Gruppennamen fest.

  • ackId ist die Identität jeder Anforderung und sollte eindeutig sein. Der Dienst sendet eine ack-Antwortnachricht, um den Prozess über das Ergebnis der Anforderung zu informieren. Weitere Informationen finden Sie unter AckId- und Ack-Antwort.

Gruppen verlassen

Format:

Legen Sie leave_group_message.group auf den Gruppennamen fest.

  • ackId ist die Identität jeder Anforderung und sollte eindeutig sein. Der Dienst sendet eine ack-Antwortnachricht, um den Prozess über das Ergebnis der Anforderung zu informieren. Weitere Informationen finden Sie unter AckId- und Ack-Antwort.

Veröffentlichen von Nachrichten

Format:

  • ackId: Die eindeutige Identität jeder Anforderung. Der Dienst sendet eine Ack-Antwortnachricht , um das Prozessergebnis der Anforderung zu benachrichtigen. Weitere Informationen finden Sie unter AckId- und Ack-Antwort.

  • dataType: Das Datenformat, das abhängig von der Datei sein protobuftextkann, oder binary je nach .dataMessageData Die empfangenden Clients können den dataType Inhalt ordnungsgemäß verarbeiten.

  • protobuf: Wenn Sie festlegensend_to_group_message.data.protobuf_data, lautet die implizite dataType .protobuf protobuf_data kann dem Nachrichtentyp Beliebig entsprechen. Alle anderen Clients erhalten protobuf-codierte Binärdateien, die vom protobuf-SDK deserialisiert werden können. Clients, die nur textbasierten Inhalt unterstützen (z. B. json.webpubsub.azure.v1 ), erhalten eine Base64-codierte Binärdatei.

  • text: Wenn Sie festlegensend_to_group_message.data.text_data, lautet die implizite dataType .text text_data sollte eine Zeichenfolge sein. Alle Clients mit anderen Protokollen erhalten eine UTF-8-codierte Zeichenfolge.

  • binary: Wenn Sie festlegensend_to_group_message.data.binary_data, lautet die implizite dataType .binary binary_data sollte ein Bytearray sein. Alle Clients mit anderen Protokollen erhalten eine unformatierte Binärdatei ohne protobuf-Codierung. Clients, die nur textbasierten Inhalt unterstützen (z. B. json.webpubsub.azure.v1 ), erhalten eine Base64-codierte Binärdatei.

Fall 1: Veröffentlichen von Textdaten

Legen Sie send_to_group_message.group auf group und send_to_group_message.data.text_data auf "text data" fest.

  • Der protobuf-Unterprotokollclient in der Gruppe group empfängt den Binärframe und kann die DownstreamMessage zum Deserialisieren verwenden.

  • Die JSON-Subprotocolclients empfangen group :

    {
        "type": "message",
        "from": "group",
        "group": "group",
        "dataType" : "text",
        "data" : "text data"
    }
    
  • Die einfachen WebSocket-Clients in group empfangener Zeichenfolge text data.

Fall 2: Veröffentlichen von protobuf-Daten

Angenommen, Sie haben eine benutzerdefinierte Nachricht:

message MyMessage {
    int32 value = 1;
}

Legen Sie send_to_group_message.group auf group und send_to_group_message.data.protobuf_data auf Any.pack(MyMessage) mit value = 1 fest.

  • Die Protobuf-Subprotocolclients erhalten group den binären Frame und können downstreamMessage verwenden, um sie deserialisieren.

  • Der Subprotocol-Client in group empfängt:

    {
        "type": "message",
        "from": "group",
        "group": "G",
        "dataType" : "protobuf",
        "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes
    }
    

    Hinweis

    Bei den Daten handelt es sich um eine Base64-codierte, deserialisierbare protobuf-Binärdatei.

Sie können die folgende Protobuf-Definition verwenden und sie mit Any.unpack() deserialisieren:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}
  • Die einfachen WebSocket-Clients erhalten group den binären Frame:

    # Show in hexadecimal
    0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01
    

Fall 3: Veröffentlichen von Binärdaten

Legen Sie send_to_group_message.group auf group und send_to_group_message.data.binary_data auf [1, 2, 3] fest.

  • Der protobuf-Unterprotokollclient in der Gruppe group empfängt den Binärframe und kann die DownstreamMessage zum Deserialisieren verwenden.

  • Der JSON-Unterprotokollclient in der Gruppe group empfängt Folgendes:

    {
        "type": "message",
        "from": "group",
        "group": "group",
        "dataType" : "binary",
        "data" : "AQID", // Base64-encoded [1,2,3]
    }
    

    Da der JSON-Unterprotokollclient nur textbasiertes Messaging unterstützt, ist die Binärdatei immer Base64-codiert.

  • Die einfachen WebSocket-Clients erhalten group die Binärdaten im Binären Frame:

    # Show in hexadecimal
    01 02 03
    

Versenden von benutzerdefinierten Ereignissen

Es gibt einen impliziten dataType, der in Abhängigkeit von dem von Ihnen festgelegten dataType entweder protobuf, text oder binary sein kann. Die Empfängerclients können den dataType nutzen, um den Inhalt ordnungsgemäß zu verarbeiten.

  • protobuf: Wenn Sie festlegenevent_message.data.protobuf_data, lautet die implizite dataType .protobuf Der protobuf_data Wert kann jeder unterstützte Protobuf-Typ sein. Der Ereignishandler empfängt die protobuf-codierten Binärdateien, die von jedem protobuf-SDK deserialisiert werden können.

  • text: Wenn Sie festlegenevent_message.data.text_data, lautet die implizite dataType .text Der text_data Wert sollte eine Zeichenfolge sein. Der Ereignishandler empfängt eine UTF-8-codierte Zeichenfolge.

  • binary: Wenn Sie festlegenevent_message.data.binary_data, lautet die implizite dataType .binary Der binary_data Wert sollte ein Bytearray sein. Der Ereignishandler empfängt den unformatierten Binärframe.

Fall 1: Senden eines Ereignisses mit Textdaten

Legen Sie event_message.data.text_data auf "text data" fest.

Der upstream-Ereignishandler empfängt eine Anforderung ähnlich wie:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: text/plain
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

text data

Die Content-Type für die CloudEvents-HTTP-Anforderung ist text/plain, wobei=dataTypetext .

Fall 2: Senden eines Ereignisses mit protobuf-Daten

Angenommen, Sie haben die folgende Nachricht von einer Kundin oder einem Kunden erhalten:

message MyMessage {
    int32 value = 1;
}

Legen Sie event_message.data.protobuf_data auf any.pack(MyMessage) mit value = 1 fest.

Der upstream-Ereignishandler empfängt eine Anforderung, die etwa wie folgt ist:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

// Just show in hexadecimal; read it as binary
0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01

Die Content-Type für die CloudEvents-HTTP-Anforderung ist application/x-protobuf, wobei=dataTypeprotobuf .

Die Daten sind eine gültige Protobuf-Binärdatei. Sie können proto und any.unpack() wie folgt für die Deserialisierung verwenden:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}

Fall 3: Senden eines Ereignisses mit Binärdaten

Legen Sie send_to_group_message.binary_data auf [1, 2, 3] fest.

Der upstream-Ereignishandler empfängt eine Anforderung ähnlich wie:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

// Just show in hexadecimal; you need to read it as binary
01 02 03 

Für dataType=binary ist der Content-Type für die CloudEvents-HTTP-Anforderung application/octet-stream. Der WebSocket-Frame kann entweder im text-Format für Textnachrichtframes oder UTF-8-codierten Binärdateien für binary-Nachrichtframes vorliegen.

Der Dienst lehnt den Client ab, wenn die Nachricht nicht dem vorgeschriebenen Format entspricht.

Antworten

Alle Antwortnachrichten entsprechen dem folgenden protobuf-Format:

message DownstreamMessage {
    oneof message {
        AckMessage ack_message = 1;
        DataMessage data_message = 2;
        SystemMessage system_message = 3;
    }
    
    message AckMessage {
        uint64 ack_id = 1;
        bool success = 2;
        optional ErrorMessage error = 3;
    
        message ErrorMessage {
            string name = 1;
            string message = 2;
        }
    }

    message DataMessage {
        string from = 1;
        optional string group = 2;
        MessageData data = 3;
    }

    message SystemMessage {
        oneof message {
            ConnectedMessage connected_message = 1;
            DisconnectedMessage disconnected_message = 2;
        }
    
        message ConnectedMessage {
            string connection_id = 1;
            string user_id = 2;
        }

        message DisconnectedMessage {
            string reason = 2;
        }
    }
}

Vom Client empfangene Nachrichten können einen beliebigen von drei Typen aufweisen: ack, message oder system.

Ack-Antwort

Wenn die Anforderung ackId enthält, gibt der Dienst eine Ack-Antwort für diese Anforderung zurück. Die Clientimplementierung sollte diesen Ack-Mechanismus verarbeiten, einschließlich:

  • Warten auf die Ack-Antwort für einen asyncawait-Vorgang
  • Timeoutüberprüfung, wenn eine Ack-Antwort innerhalb eines bestimmten Zeitraums nicht empfangen wird

Die Clientimplementierung sollte immer zuerst überprüfen, ob der success-Status true oder false entspricht. Wenn der success-Status false entspricht, kann der Client Fehlerdetails aus der error-Eigenschaft lesen.

Reaktion auf die Nachricht

Clients können Nachrichten empfangen, die von einer Gruppe veröffentlicht wurden, der der Client beigetreten ist. Alternativ können sie Nachrichten von der Serververwaltungsrolle empfangen, wenn der Server Nachrichten an einen bestimmten Client oder bestimmte Benutzer*innen sendet.

In den folgenden Szenarios erhalten Sie immer eine DownstreamMessage.DataMessage-Nachricht:

  • Wenn die Nachricht von einer Gruppe stammt, wird für fromgroup angegeben. Wenn die Nachricht vom Server stammt, wird für fromserver angegeben.
  • Wenn die Nachricht von einer Gruppe stammt, ist group der Gruppenname.

Der dataType von Sender*innen verursacht, dass eine der folgenden Nachrichten gesendet wird:

  • Wenn der dataTypetext lautet, verwenden Sie message_response_message.data.text_data.
  • Wenn der dataTypebinary lautet, verwenden Sie message_response_message.data.binary_data.
  • Wenn der dataTypeprotobuf lautet, verwenden Sie message_response_message.data.protobuf_data.
  • Wenn der dataTypejson lautet, verwenden Sie message_response_message.data.text_data, und der Inhalt ist eine serialisierte JSON-Zeichenfolge.

Systemantwort

Der Web PubSub-Dienst kann auch systembezogene Antworten an den Client senden.

Verbunden

Wenn der Client eine Verbindung mit dem Dienst herstellt, erhalten Sie eine DownstreamMessage.SystemMessage.ConnectedMessage-Nachricht.

Verbindung getrennt

Wenn der Server die Verbindung schließt oder der Dienst den Client ablehnt, erhalten Sie eine DownstreamMessage.SystemMessage.DisconnectedMessage-Nachricht.

Nächste Schritte

Erstellen Sie mithilfe dieser Ressourcen Ihre eigene Anwendung: