Podprotocol protokołu Web PubSub obsługiwane przez usługę Azure WebSocket protobuf
W tym dokumencie opisano podprotocol protobuf.webpubsub.azure.v1
.
Gdy klient korzysta z tego podprotokolu, zarówno ramki danych wychodzących, jak i przychodzących powinny być ładunkami protokołu (protobuf).
Omówienie
Podprotocol protobuf.webpubsub.azure.v1
umożliwia klientowi bezpośrednie wykonywanie subskrypcji publikowania (PubSub) zamiast rundy na serwerze nadrzędnym. Połączenie protokołu WebSocket z protobuf.webpubsub.azure.v1
podprotokolem jest nazywane klientem protokołu WebSocket PubSub.
Na przykład w języku JavaScript można utworzyć klienta protokołu WebSocket PubSub za pomocą podprotocol protobuf za pomocą polecenia:
// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');
W przypadku prostego klienta protokołu WebSocket serwer ma niezbędną rolę obsługi zdarzeń od klientów. Proste połączenie protokołu WebSocket zawsze wyzwala message
zdarzenie podczas wysyłania komunikatów i zawsze opiera się na stronie serwera w celu przetwarzania komunikatów i wykonywania innych operacji. Za pomocą protobuf.webpubsub.azure.v1
podprotocol autoryzowanego klienta może dołączyć do grupy przy użyciu żądań sprzężenia i publikowania komunikatów w grupie przy użyciu żądań publikowania bezpośrednio. Klient może również kierować komunikaty do różnych programów obsługi zdarzeń nadrzędnych przy użyciu żądań zdarzeń w celu dostosowania zdarzenia , do którego należy komunikat.
Uwaga
Obecnie usługa Web PubSub obsługuje tylko proto3.
Uprawnienia
Klient protokołu WebSocket PubSub może publikować tylko na innych klientach, gdy jest autoryzowany. Przypisany roles
do klienta określ uprawnienia przyznane klientowi:
Rola | Uprawnienie |
---|---|
Nieokreślona | Klient może wysyłać żądania zdarzeń. |
webpubsub.joinLeaveGroup |
Klient może dołączyć/pozostawić dowolną grupę. |
webpubsub.sendToGroup |
Klient może publikować komunikaty w dowolnej grupie. |
webpubsub.joinLeaveGroup.<group> |
Klient może dołączyć/opuścić grupę <group> . |
webpubsub.sendToGroup.<group> |
Klient może publikować komunikaty w grupie <group> . |
Serwer może dynamicznie udzielać lub odwoływać uprawnienia klienta za pośrednictwem interfejsów API REST lub zestawów SDK serwera.
Żądania
Wszystkie komunikaty żądań są zgodne z następującym formatem protobuf:
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;
}
}
Dołączanie grup
Format:
Ustaw join_group_message.group
nazwę grupy.
ackId
to tożsamość każdego żądania i powinna być unikatowa. Usługa wysyła komunikat odpowiedzi ack, aby powiadomić wynik procesu żądania. Więcej szczegółów można znaleźć na stronie AckId i Ack Response
Pozostaw grupy
Format:
Ustaw leave_group_message.group
nazwę grupy.
ackId
to tożsamość każdego żądania i powinna być unikatowa. Usługa wysyła komunikat odpowiedzi ack, aby powiadomić wynik procesu żądania. Więcej szczegółów można znaleźć na stronie AckId i Ack Response
Publikowanie komunikatów
Format:
ackId
: unikatowa tożsamość każdego żądania. Usługa wysyła komunikat odpowiedzi ack, aby powiadomić wynik procesu żądania. Więcej szczegółów można znaleźć na stronie AckId i Ack ResponsedataType
: format danych, który może miećprotobuf
wartość ,text
lubbinary
w zależności oddata
wartości w plikuMessageData
. Klienci odbierający mogą używaćdataType
do poprawnego przetwarzania zawartości.protobuf
: Po ustawieniusend_to_group_message.data.protobuf_data
parametru niejawnydataType
toprotobuf
.protobuf_data
może mieć wartość Dowolny typ komunikatu. Wszyscy inni klienci otrzymują kodowany protobuf binarny, który może być deserializowany przez zestaw SDK protobuf. Klienci, którzy obsługują tylko zawartość tekstową (na przykładjson.webpubsub.azure.v1
), otrzymują plik binarny zakodowany w formacie Base64.text
: Po ustawieniusend_to_group_message.data.text_data
parametru niejawnydataType
totext
.text_data
powinien być ciągiem. Wszyscy klienci z innymi protokołami otrzymują ciąg zakodowany w formacie UTF-8.binary
: Po ustawieniusend_to_group_message.data.binary_data
parametru niejawnydataType
tobinary
.binary_data
powinna być tablicą bajtów. Wszyscy klienci z innymi protokołami otrzymują nieprzetworzone dane binarne bez kodowania protobuf. Klienci, którzy obsługują tylko zawartość tekstową (na przykładjson.webpubsub.azure.v1
), otrzymują plik binarny zakodowany w formacie Base64.
Przypadek 1. Publikowanie danych tekstowych
Ustaw send_to_group_message.group
wartość group
na , i ustaw wartość send_to_group_message.data.text_data
"text data"
.
Klient podrzędny protobuf w grupie
group
odbiera ramkę binarną i może użyć parametru DownstreamMessage do deserializacji.Klienci podrzędni JSON odbierają
group
:{ "type": "message", "from": "group", "group": "group", "dataType" : "text", "data" : "text data" }
Prosti klienci protokołu WebSocket w
group
ciągutext data
odbierania .
Przypadek 2. Publikowanie danych protobuf
Załóżmy, że masz niestandardowy komunikat:
message MyMessage {
int32 value = 1;
}
Ustaw send_to_group_message.group
wartość na group
i send_to_group_message.data.protobuf_data
na Any.pack(MyMessage)
wartość z wartością value = 1
.
Klienci podrzędni protobuf w
group
odbieraniu ramki binarnej i mogą używać parametru DownstreamMessage do deserializacji.Klient subprotocol w programie
group
odbiera:{ "type": "message", "from": "group", "group": "G", "dataType" : "protobuf", "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes }
Uwaga
Dane są plikami binarnymi protobuf zakodowanymi w formacie Base64.
Możesz użyć następującej definicji protobuf i użyć Any.unpack()
jej do deserializacji:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Prosti klienci protokołu WebSocket odbierają
group
ramkę binarną:# 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
Przypadek 3. Publikowanie danych binarnych
Ustaw send_to_group_message.group
wartość group
na , i ustaw wartość send_to_group_message.data.binary_data
[1, 2, 3]
.
Klient podrzędny protobuf w grupie
group
odbiera ramkę binarną i może użyć parametru DownstreamMessage do deserializacji.Klient podrzędny JSON w grupie
group
otrzymuje:{ "type": "message", "from": "group", "group": "group", "dataType" : "binary", "data" : "AQID", // Base64-encoded [1,2,3] }
Ponieważ klient podrzędny JSON obsługuje tylko komunikaty tekstowe, plik binarny jest zawsze zakodowany w formacie Base64.
Prosti klienci protokołu WebSocket odbierają
group
dane binarne w ramce binarnej:# Show in hexadecimal 01 02 03
Wysyłanie zdarzeń niestandardowych
Istnieje niejawny dataType
element , który może mieć protobuf
wartość , text
lub binary
, w zależności od ustawionego dataType
ustawienia. Klienci odbiorcy mogą używać dataType
do poprawnego obsługi zawartości.
protobuf
: Po ustawieniuevent_message.data.protobuf_data
parametru niejawnydataType
toprotobuf
. Wartośćprotobuf_data
może być dowolnym obsługiwanym typem protobuf. Procedura obsługi zdarzeń odbiera kodowany plik binarny protobuf, który może być deserializowany przez dowolny zestaw SDK protobuf.text
: Po ustawieniuevent_message.data.text_data
parametru niejawnydataType
totext
. Wartośćtext_data
powinna być ciągiem. Procedura obsługi zdarzeń odbiera ciąg zakodowany w formacie UTF-8.binary
: Po ustawieniuevent_message.data.binary_data
parametru niejawnydataType
tobinary
. Wartośćbinary_data
powinna być tablicą bajtów. Procedura obsługi zdarzeń odbiera nieprzetworzonej ramki binarnej.
Przypadek 1. Wysyłanie zdarzenia z danymi tekstowymi
Ustaw wartość opcji event_message.data.text_data
na "text data"
.
Program obsługi zdarzeń nadrzędnych odbiera żądanie podobne do:
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
Dla Content-Type
żądania HTTP CloudEvents to text/plain
, gdzie=dataType
text
.
Przypadek 2. Wysyłanie zdarzenia z danymi protobuf
Załóżmy, że otrzymano następujący komunikat klienta:
message MyMessage {
int32 value = 1;
}
Ustaw event_message.data.protobuf_data
na z any.pack(MyMessage)
value = 1
Program obsługi zdarzeń nadrzędnych odbiera żądanie podobne do następującego:
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
Dla Content-Type
żądania HTTP CloudEvents to application/x-protobuf
, gdzie=dataType
protobuf
.
Dane są prawidłowym plikiem binarnym protobuf. Możesz użyć następującego proto
polecenia i any.unpack()
wykonać deserializowanie go:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Przypadek 3. Wysyłanie zdarzenia z danymi binarnymi
Ustaw wartość opcji send_to_group_message.binary_data
na [1, 2, 3]
.
Program obsługi zdarzeń nadrzędnych odbiera żądanie podobne do:
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
W przypadku dataType
=binary
elementu dla Content-Type
żądania HTTP CloudEvents to .application/octet-stream
Ramka Protokołu WebSocket może być w text
formacie ramek wiadomości tekstowych lub plików binarnych zakodowanych w formacie UTF-8 dla binary
ramek komunikatów.
Usługa odrzuca klienta, jeśli komunikat nie jest zgodny z określonym formatem.
Odpowiedzi
Wszystkie komunikaty odpowiedzi są zgodne z następującym formatem protobuf:
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;
}
}
}
Komunikaty odbierane przez klienta mogą znajdować się w dowolnym z trzech typów: ack
, message
lub system
.
Odpowiedź Ack
Jeśli żądanie zawiera ackId
, usługa zwraca odpowiedź ack dla tego żądania. Implementacja klienta powinna obsługiwać ten mechanizm ack, w tym:
- Oczekiwanie na odpowiedź ack dla
async
await
operacji. - Sprawdzanie limitu czasu, gdy odpowiedź ack nie jest odbierana w określonym okresie.
Implementacja klienta powinna zawsze najpierw sprawdzać, czy success
stan to true
, czy false
. success
Gdy stan to false
, klient może odczytać z error
właściwości , aby uzyskać szczegółowe informacje o błędzie.
Odpowiedź na komunikat
Klienci mogą odbierać komunikaty opublikowane z grupy, do których dołączył klient. Mogą też odbierać komunikaty z roli zarządzania serwerem, gdy serwer wysyła komunikaty do określonego klienta lub określonego użytkownika.
Zawsze będziesz otrzymywać DownstreamMessage.DataMessage
komunikat w następujących scenariuszach:
- Gdy komunikat pochodzi z grupy,
from
togroup
. Gdy komunikat pochodzi z serwera,from
toserver
. - Gdy komunikat pochodzi z grupy,
group
to nazwa grupy.
Nadawca dataType
spowoduje wysłanie jednego z następujących komunikatów:
- Jeśli
dataType
parametr ma wartośćtext
, użyj poleceniamessage_response_message.data.text_data
. - Jeśli
dataType
parametr ma wartośćbinary
, użyj poleceniamessage_response_message.data.binary_data
. - Jeśli
dataType
parametr ma wartośćprotobuf
, użyj poleceniamessage_response_message.data.protobuf_data
. - Jeśli
dataType
element tojson
, użyj elementumessage_response_message.data.text_data
, a zawartość jest serializowanym ciągiem JSON.
Odpowiedź systemu
Usługa Web PubSub może również wysyłać odpowiedzi związane z systemem do klienta.
Połączono
Gdy klient nawiązuje połączenie z usługą DownstreamMessage.SystemMessage.ConnectedMessage
, zostanie wyświetlony komunikat.
Odłączony
Gdy serwer zamknie połączenie lub usługa odrzuci klienta, zostanie wyświetlony DownstreamMessage.SystemMessage.DisconnectedMessage
komunikat.
Następne kroki
Użyj tych zasobów, aby rozpocząć tworzenie własnej aplikacji: