Azure Web PubSub – zuverlässiges JSON-WebSocket-Unterprotokoll

Das JSON-WebSocket-Unterprotokoll, json.reliable.webpubsub.azure.v1, ermöglicht den äußerst zuverlässigen Austausch von Veröffentlichungs-/Abonnentennachrichten direkt zwischen Clients über den Dienst ohne Roundtrip zum Upstreamserver.

In diesem Dokument wird das Unterprotokoll json.reliable.webpubsub.azure.v1 beschrieben.

Wenn WebSocket-Clientverbindungen aufgrund von zeitweiligen Netzwerkproblemen unterbrochen werden, können Nachrichten verloren gehen. In einem Pub/Sub-System sind Herausgeber und Abonnenten voneinander entkoppelt, sodass Verbindungstrennungen oder Nachrichtenverluste von Abonnenten möglicherweise nicht erkannt werden.

Um zeitweilige Netzwerkprobleme zu überwinden und eine zuverlässige Nachrichtenübermittlung aufrechtzuerhalten, können Sie das Azure WebPubSub-Unterprotokoll json.reliable.webpubsub.azure.v1 verwenden und einen zuverlässigen PubSub WebSocket-Client erstellen.

Ein zuverlässiger PubSub-WebSocket-Client kann Folgendes:

In JavaScript können Sie beispielsweise einen zuverlässigen PubSub-WebSocket-Client mit dem folgenden JavaScript-Code erstellen:

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

Im Artikel zum Erstellen zuverlässiger Clients finden Sie Informationen, um die erneute Verbindungsherstellung und Nachrichtenzuverlässigkeit für Herausgeber- und Abonnentenclients zu implementieren.

Wenn der Client dieses Unterprotokoll verwendet, wird erwartet, dass sowohl der ausgehende als auch der eingehende Datenframe JSON-Nutzdaten enthalten.

Berechtigungen

Ein PubSub-WebSocket-Client kann nur dann auf anderen Clients veröffentlichen, wenn er dazu autorisiert ist. Die dem Client zugewiesenen roles bestimmen die Berechtigungen, 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/diese verlassen.
webpubsub.sendToGroup.<group> Der Client kann Nachrichten in der Gruppe <group> veröffentlichen.
webpubsub.joinLeaveGroups.<pattern> Der Client kann jeder Gruppe beitreten/verlassen, deren Namen übereinstimmen <pattern> (siehe Rollenmuster für Wildcard-Gruppen).
webpubsub.sendToGroups.<pattern> Der Client kann Nachrichten in jeder Gruppe veröffentlichen, deren Namen übereinstimmen <pattern> (siehe Rollenmuster für Wildcardgruppen).

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

Hinweis

Wildcardrollen (z. B. webpubsub.sendToGroups.<pattern>) werden während der Laufzeit nicht in REST-APIs oder Server-SDKs unterstützt.

Requests

Gruppen beitreten

Format:

{
    "type": "joinGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • 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. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort

Gruppen verlassen

Format:

{
    "type": "leaveGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • 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. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort

Veröffentlichen von Nachrichten

Format:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "ackId" : 1,
    "noEcho": true|false,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • 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. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort
  • noEcho ist optional. Wenn dies auf „true“ festgelegt ist, wird diese Nachricht nicht an dieselbe Verbindung zurückgesendet. Wenn keine Festlegung erfolgt, ist der Standardwert FALSE.
  • dataType kann auf json, text oder binary festgelegt werden.
    • json: data kann ein beliebiger Typ sein, der von JSON unterstützt und in seinem jeweiligen Zustand veröffentlicht wird. Wenn dataType nicht angegeben ist, wird dieser Wert standardmäßig auf json festgelegt.
    • text: data sollte im Zeichenfolgenformat vorliegen, und die Zeichenfolgendaten werden veröffentlicht.
    • binary: data sollte im Base64-Format vorliegen, und die Binärdaten werden veröffentlicht.

Fall 1: Veröffentlichen von Textdaten:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "text",
    "data": "text data",
    "ackId": 1
}
  • Die Unterprotokollclients in <group_name> empfangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "text",
    "data" : "text data"
}
  • Die einfachen WebSocket-Clients in <group_name> empfangen die Zeichenfolge text data.

Fall 2: Veröffentlichen von JSON-Daten:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    }
}
  • Die Unterprotokollclients in <group_name> empfangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "json",
    "data" : {
        "hello": "world"
    }
}
  • Die einfachen WebSocket-Clients in <group_name> empfangen die serialisierte Zeichenfolge {"hello": "world"}.

Fall 3: Veröffentlichen von Binärdaten:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "binary",
    "data": "<base64_binary>",
    "ackId": 1
}
  • Die Unterprotokollclients in <group_name> empfangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "binary",
    "data" : "<base64_binary>", 
}
  • Die einfachen WebSocket-Clients in <group_name> empfangen die binären Daten im binären Frame.

Versenden von benutzerdefinierten Ereignissen

Format:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • 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. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort

dataType kann text, binary oder json sein.

  • json: Die Daten können ein beliebiger Typ sein, der von JSON unterstützt wird, und werden in ihrem jeweiligen Zustand veröffentlicht. Der Standardwert ist json.
  • text: Die Daten liegen im Zeichenfolgenformat vor, und die Zeichenfolgendaten werden veröffentlicht.
  • binary: Die Daten liegen im base64-Format vor, und die binären Daten werden veröffentlicht.

Fall 1: Ereignis mit Textdaten versenden:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "text",
    "data": "text data", 
}

Der Upstreamereignishandler empfängt Daten ä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

Content-Type für die CloudEvents-HTTP-Anforderung ist text/plain, wenn dataType den Wert text hat.

Fall 2: Ereignis mit JSON-Daten versenden:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json",
    "data": {
        "hello": "world"
    }, 
}

Der Upstreamereignishandler empfängt Daten ähnlich wie:

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>

{
    "hello": "world"
}

Content-Type für die CloudEvents-HTTP-Anforderung ist application/json, wenn dataType den Wert json hat.

Fall 3: Ereignis mit Binärdaten versenden:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "binary",
    "data": "base64_binary", 
}

Der Upstreamereignishandler empfängt Daten ä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>

binary

Content-Type für die CloudEvents-HTTP-Anforderung ist application/octet-stream, wenn dataType den Wert binary hat. Der WebSocket-Frame kann entweder das text-Format für Textnachricht-Frames aufweisen oder UTF8-codierte Binärdateien für binary-Nachrichtframes enthalten.

Der Web PubSub-Dienst lehnt den Client ab, wenn die Nachricht nicht dem beschriebenen Format entspricht.

Ping

Format:

{
    "type": "ping",
}

Der Client kann eine ping-Nachricht an den Dienst senden, um den Web PubSub-Dienst zu aktivieren, damit die Aktivität des Clients erkannt werden kann.

Sequenzbestätigung

Format:

{
    "type": "sequenceAck",
    "sequenceId": "<sequenceId>",
}

Der zuverlässige PubSub-WebSocket-Client muss eine Nachricht zur Sequenzbestätigung senden, nachdem eine Nachricht vom Dienst empfangen wurde. Weitere Informationen finden Sie im Artikel zum Erstellen zuverlässiger Clients.

  • sequenceId ist eine inkrementelle uint64-Zahl aus der empfangenen Nachricht.

Antworten

Vom Client empfangene Nachrichten können verschiedene Typen aufweisen: ack, message, system und pong. Nachrichten vom Typ message verfügen über die Eigenschaft sequenceId. Der Client muss eine Sequenzbestätigung an den Dienst senden, sobald er eine Nachricht empfängt.

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, u. a. durch Warten auf die Ack-Antwort mit einem asyncawait-Vorgang, und einen Timeouthandler aufweisen, wenn die Ack-Antwort nicht während eines bestimmten Zeitraums empfangen wird.

Format:

{
    "type": "ack",
    "ackId": 1, // The ack id for the request to ack
    "success": false, // true or false
    "error": {
        "name": "Forbidden|InternalServerError|Duplicate",
        "message": "<error_detail>"
    }
}

Die Clientimplementierung SOLLTE immer zuerst überprüfen, ob successtrue oder false ist. Nur wenn successfalse ist, liest der Client aus error.

Reaktion auf die Nachricht

Clients können Nachrichten entweder von einer Gruppe empfangen, in die der Client eingebunden ist, oder vom Server. Dieser verwendet eine Serververwaltungsrolle und sendet Nachrichten an bestimmte Clients oder Benutzer.

  1. Die Antwortnachricht einer Gruppe:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "group",
        "group": "<group_name>",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
        "fromUserId": "abc"
    }
    
  2. Die Antwortnachricht vom Server:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
    }
    

Fall 1: Senden der Daten Hello World an die Verbindung über die REST-API mit Content-Type=text/plain

  • Ein einfacher WebSocket-Client empfängt einen WebSocket-Textframe mit Daten: Hello World;

  • Ein PubSub-WebSocket-Client empfängt die Nachricht in JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "text",
        "data": "Hello World", 
    }
    

Fall 2: Senden der Daten { "Hello" : "World"} an die Verbindung über die REST-API mit Content-Type=application/json

  • Ein einfacher WebSocket-Client empfängt einen WebSocket-Textframe mit Daten im Zeichenfolgenformat: { "Hello" : "World"};

  • Ein PubSub-WebSocket-Client empfängt die Nachricht in JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "json",
        "data": {
            "Hello": "World"
        }
    }
    

Wenn die REST-API eine Zeichenfolge Hello World mit dem Inhaltstyp application/json sendet, empfängt der einfache WebSocket-Client die JSON-Zeichenfolge "Hello World", die von " umschlossen ist.

Fall 3: Senden der von Binärdaten an die Verbindung über die REST-API mit Content-Type=application/octet-stream

  • Ein einfacher WebSocket-Client empfängt einen binären WebSocket-Frame mit den Binärdaten.

  • Ein PubSub-WebSocket-Client empfängt die Nachricht in JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "binary",
        "data": "<base64_binary>"
    }
    

Systemantwort

Der Web PubSub-Dienst kann systembezogene Antworten an den Client zurückgeben.

Pong-Antwort

Der Web PubSub-Dienst sendet eine pong-Nachricht an den Client, wenn er eine ping-Nachricht vom Client empfängt.

Format:

{
    "type": "pong",
}

Verbunden

Die Antwort auf die Clientverbindungsanforderung:

{
    "type": "system",
    "event": "connected",
    "userId": "user1",
    "connectionId": "abcdefghijklmnop",
    "reconnectionToken": "<token>"
}

connectionId und reconnectionToken werden für die erneute Verbindungsherstellung verwendet. Stellen Sie eine Verbindungsanforderung mit dem URI für die erneute Verbindungsherstellung:

wss://<service-endpoint>/client/hubs/<hub>?awps_connection_id=<connectionId>&awps_reconnection_token=<reconnectionToken>

Weitere Informationen finden Sie unter Wiederherstellen einer Verbindung

Getrennt

Die Antwort, wenn der Server die Verbindung schließt oder wenn der Dienst die Clientverbindung ablehnt:

{
    "type": "system",
    "event": "disconnected",
    "message": "reason"
}

Nächste Schritte

Erstellen Sie mithilfe dieser Ressourcen Ihre eigene Anwendung: