Поделиться через


Поддерживаемый 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 Response

  • dataType: формат данных, который может быть 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или textbinaryв зависимости от заданного 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-streamHTTP-запрос 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 сообщение.

Следующие шаги

Используйте эти ресурсы для начала создания собственного приложения: