Поддерживаемый protobuf WebSocket subprotocol в Azure Web PubSub
В этом документе описывается подпротокол protobuf.webpubsub.azure.v1
.
Если клиент использует этот подпротокол, то как исходящие, так и входящие кадры данных, как ожидается, будут полезные данные буферов протокола (protobuf).
Обзор
Subprotocol protobuf.webpubsub.azure.v1
позволяет клиенту выполнять подписку на публикацию (PubSub) напрямую, а не выполнять круговую поездку на вышестоящий сервер. Подключение WebSocket к protobuf.webpubsub.azure.v1
подпротоколу называется клиентом PubSub WebSocket.
Например, в JavaScript можно создать клиент PubSub WebSocket с помощью подпротокола protobuf:
// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');
Для простого клиента WebSocket сервер имеет необходимую роль обработки событий от клиентов. Простое подключение WebSocket всегда активирует message
событие при отправке сообщений, и оно всегда зависит от стороны сервера для обработки сообщений и выполнения других операций. С помощью protobuf.webpubsub.azure.v1
подпротокола авторизованный клиент может присоединиться к группе с помощью запросов на присоединение и опубликовать сообщения в группе с помощью запросов публикации напрямую. Клиент также может направлять сообщения в различные обработчики событий вышестоящего потока с помощью запросов событий для настройки события , к которому принадлежит сообщение.
Примечание.
В настоящее время служба Web PubSub поддерживает только proto3.
Разрешения
Клиент PubSub WebSocket может публиковаться только в других клиентах, когда он авторизован. Назначенные roles
клиенту разрешения определяются клиентом:
Роль | Разрешение |
---|---|
Не указано | Клиент может отправлять запросы событий. |
webpubsub.joinLeaveGroup |
Клиент может присоединиться к любой группе или выйти из нее. |
webpubsub.sendToGroup |
Клиент может публиковать сообщения в любой группе. |
webpubsub.joinLeaveGroup.<group> |
Клиент может присоединиться или оставить группу <group> . |
webpubsub.sendToGroup.<group> |
Клиент может публиковать сообщения в группе <group> . |
Сервер может динамически предоставлять или отзывать разрешения клиента с помощью REST API или пакетов SDK сервера.
Запросы
Все сообщения запроса соответствуют следующему формату 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;
}
}
Присоединение к группам
Формат:
Задайте join_group_message.group
имя группы.
ackId
— это удостоверение каждого запроса и должно быть уникальным. Служба отправляет ответное сообщение об ошибке, чтобы уведомить результат процесса запроса. Дополнительные сведения можно найти на сайте AckId и Ack Response
Выход из групп
Формат:
Задайте leave_group_message.group
имя группы.
ackId
— это удостоверение каждого запроса и должно быть уникальным. Служба отправляет ответное сообщение об ошибке, чтобы уведомить результат процесса запроса. Дополнительные сведения можно найти на сайте AckId и Ack Response
публикация сообщений.
Формат:
ackId
: уникальное удостоверение каждого запроса. Служба отправляет сообщение ответа ack, чтобы уведомить результат процесса запроса. Дополнительные сведения можно найти на сайте AckId и Ack ResponsedataType
: формат данных, который может бытьprotobuf
,text
илиbinary
в зависимости от типаdata
MessageData
в . Принимающие клиенты могут использоватьdataType
для правильной обработки содержимого.protobuf
: при установкеsend_to_group_message.data.protobuf_data
неявноеdataType
значениеprotobuf
.protobuf_data
может иметь тип любого сообщения. Все остальные клиенты получают двоичный файл в кодировке protobuf, который можно десериализировать с помощью пакета SDK protobuf. Клиенты, поддерживающие только текстовое содержимое (например,json.webpubsub.azure.v1
) получают двоичный файл в кодировке Base64.text
: при установкеsend_to_group_message.data.text_data
неявноеdataType
значениеtext
.text_data
должен быть строкой. Все клиенты с другими протоколами получают строку в кодировке UTF-8.binary
: при установкеsend_to_group_message.data.binary_data
неявноеdataType
значениеbinary
.binary_data
должен быть массивом байтов. Все клиенты с другими протоколами получают необработанный двоичный файл без кодировки protobuf. Клиенты, поддерживающие только текстовое содержимое (например,json.webpubsub.azure.v1
) получают двоичный файл в кодировке Base64.
Случай 1. Публикация текстовых данных
Установите значение send_to_group_message.group
,и задайте для "text data"
нее значение send_to_group_message.data.text_data
.group
Клиент protobuf subprotocol в группе
group
получает двоичный кадр и может использовать DownstreamMessage для десериализации.Клиенты подпротокола JSON в
group
получении:{ "type": "message", "from": "group", "group": "group", "dataType" : "text", "data" : "text data" }
Простые клиенты WebSocket в
group
строкеtext data
получения.
Случай 2. Публикация данных protobuf
Предположим, что у вас есть пользовательское сообщение:
message MyMessage {
int32 value = 1;
}
Установите и group
установите для нее значение Any.pack(MyMessage)
value = 1
.send_to_group_message.group
send_to_group_message.data.protobuf_data
Клиенты protobuf subprotocol в
group
получении двоичного кадра и могут использовать DownstreamMessage для десериализации.Клиент подпротокол
group
получает:{ "type": "message", "from": "group", "group": "G", "dataType" : "protobuf", "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes }
Примечание.
Данные являются двоичным файлом protobuf в кодировке Base64, десериализируемым.
Вы можете использовать следующее определение protobuf и использовать Any.unpack()
для десериализации:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Простые клиенты WebSocket в
group
двоичном кадре:# 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
Случай 3. Публикация двоичных данных
Установите значение send_to_group_message.group
,и задайте для [1, 2, 3]
нее значение send_to_group_message.data.binary_data
.group
Клиент protobuf subprotocol в группе
group
получает двоичный кадр и может использовать DownstreamMessage для десериализации.Клиент подпротокола JSON в группе
group
получает:{ "type": "message", "from": "group", "group": "group", "dataType" : "binary", "data" : "AQID", // Base64-encoded [1,2,3] }
Так как клиент JSON subprotocol поддерживает только текстовые сообщения, двоичный файл всегда закодирован в Кодировке Base64.
Простые клиенты WebSocket в
group
получении двоичных данных в двоичном кадре:# Show in hexadecimal 01 02 03
Отправка пользовательских событий
Существует неявное dataType
значение, которое может быть protobuf
или text
binary
в зависимости от заданного dataType
набора. Клиенты-получатели могут использовать dataType
для правильной обработки содержимого.
protobuf
: при установкеevent_message.data.protobuf_data
неявноеdataType
значениеprotobuf
. Значениеprotobuf_data
может быть любым поддерживаемым типом protobuf. Обработчик событий получает двоичный файл в кодировке protobuf, который может быть десериализирован любым пакетом SDK protobuf.text
: при установкеevent_message.data.text_data
неявноеdataType
значениеtext
. Значениеtext_data
должно быть строкой. Обработчик событий получает строку в кодировке UTF-8.binary
: при установкеevent_message.data.binary_data
неявноеdataType
значениеbinary
. Значениеbinary_data
должно быть массивом байтов. Обработчик событий получает необработанный двоичный кадр.
Случай 1. Отправка события с текстовыми данными
Задайте для параметра event_message.data.text_data
значение "text data"
.
Обработчик событий вышестоящего потока получает запрос, аналогичный следующему:
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
HTTP-запроса CloudEvents используется text/plain
, где dataType
=text
.
Случай 2. Отправка события с данными protobuf
Предположим, что вы получили следующее сообщение клиента:
message MyMessage {
int32 value = 1;
}
Задать event_message.data.protobuf_data
значение any.pack(MyMessage)
с помощью value = 1
Обработчик событий вышестоящей передачи получает запрос, аналогичный следующему:
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
Для Content-Type
HTTP-запроса CloudEvents используется application/x-protobuf
, где dataType
=protobuf
.
Данные являются допустимым двоичным файлом protobuf. Для десериализации можно использовать следующее proto
any.unpack()
:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Случай 3. Отправка события с двоичными данными
Задайте для параметра send_to_group_message.binary_data
значение [1, 2, 3]
.
Обработчик событий вышестоящего потока получает запрос, аналогичный следующему:
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
Для dataType
=binary
этого Content-Type
используется application/octet-stream
HTTP-запрос CloudEvents. Кадр WebSocket может быть в text
формате для текстовых кадров сообщений или двоичных файлов в кодировке UTF-8 для binary
кадров сообщений.
Служба отклоняет клиент, если сообщение не соответствует указанному формату.
Отклики
Все сообщения ответа соответствуют следующему формату 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;
}
}
}
Сообщения, полученные клиентом, могут находиться в любом из трех типов: ack
, message
или system
.
Отклик ACK
Если запрос содержит ackId
, служба возвращает ответ ack для этого запроса. Реализация клиента должна обрабатывать этот механизм ack, в том числе:
- Ожидание ответа взлома для
async
await
операции. - Наличие проверки времени ожидания, когда ответ ack не получен в течение определенного периода.
Реализация клиента всегда должна проверять, является true
ли success
состояние или false
. success
Когда состояние равноfalse
, клиент может прочитать из свойства сведения об ошибкеerror
.
Ответ на сообщение
Клиенты могут получать сообщения, опубликованные из группы, присоединенной к клиенту. Или они могут получать сообщения от роли управления серверами, когда сервер отправляет сообщения конкретному клиенту или конкретному пользователю.
Вы всегда получите DownstreamMessage.DataMessage
сообщение в следующих сценариях:
- Если сообщение находится из группы,
from
имеет значениеgroup
. Если сообщение находится с сервера,from
имеет значениеserver
. - Если сообщение находится из группы,
group
— это имя группы.
Отправитель dataType
приведет к отправке одного из следующих сообщений:
- Если
dataType
этоtext
, используйтеmessage_response_message.data.text_data
. - Если
dataType
этоbinary
, используйтеmessage_response_message.data.binary_data
. - Если
dataType
этоprotobuf
, используйтеmessage_response_message.data.protobuf_data
. - Если
dataType
используетсяjson
, иmessage_response_message.data.text_data
содержимое является сериализованной строкой JSON.
Отклик системы
Служба Web PubSub также может отправлять клиенту отклики, связанные с системой.
Connected
Когда клиент подключается к службе, вы получите DownstreamMessage.SystemMessage.ConnectedMessage
сообщение.
Отключено
Когда сервер закрывает подключение или служба отклоняет клиент, вы получаете DownstreamMessage.SystemMessage.DisconnectedMessage
сообщение.
Следующие шаги
Используйте эти ресурсы для начала создания собственного приложения: