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 seinprotobuf
text
kann, oderbinary
je nach .data
MessageData
Die empfangenden Clients können dendataType
Inhalt ordnungsgemäß verarbeiten.protobuf
: Wenn Sie festlegensend_to_group_message.data.protobuf_data
, lautet die implizitedataType
.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 implizitedataType
.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 implizitedataType
.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 Zeichenfolgetext 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 implizitedataType
.protobuf
Derprotobuf_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 implizitedataType
.text
Dertext_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 implizitedataType
.binary
Derbinary_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=dataType
text
.
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=dataType
protobuf
.
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
async
await
-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
from
group
angegeben. Wenn die Nachricht vom Server stammt, wird fürfrom
server
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
dataType
text
lautet, verwenden Siemessage_response_message.data.text_data
. - Wenn der
dataType
binary
lautet, verwenden Siemessage_response_message.data.binary_data
. - Wenn der
dataType
protobuf
lautet, verwenden Siemessage_response_message.data.protobuf_data
. - Wenn der
dataType
json
lautet, verwenden Siemessage_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: