Создание надежного websocket с помощью подпротокола

При удалении подключений клиентов Websocket из-за периодических проблем с сетью сообщения могут быть потеряны. В пабе или подсистеме издатели отделены от подписчиков, поэтому издатели могут не обнаружить удаляемое подключение или потерю сообщения. Важно, чтобы клиенты преодолели периодические проблемы с сетью и обеспечить надежную доставку сообщений. Для этого можно создать надежный клиент Websocket с помощью надежных подпротоколов Azure Web PubSub.

Надежный протокол

Служба Web PubSub поддерживает два надежных субпротокола json.reliable.webpubsub.azure.v1 и protobuf.reliable.webpubsub.azure.v1. Клиенты должны следовать частям издателя, подписчика и восстановления подпротокола, чтобы обеспечить надежность. Не удалось правильно реализовать подпротокол, может привести к тому, что доставка сообщений не работает должным образом или служба завершает клиент из-за нарушений протокола.

Простой способ. Использование клиентского пакета SDK

Самый простой способ создания надежного клиента — использовать клиентский пакет SDK. Клиентский пакет SDK реализует спецификацию клиента Web PubSub и используется json.reliable.webpubsub.azure.v1 по умолчанию. Ознакомьтесь с разделом "Публикация и подписка" среди клиентов для быстрого запуска.

Трудный путь - реализовать рукой

В следующем руководстве описана важная часть реализации спецификации клиента Web PubSub. Это руководство не для людей, ищущих быстрого начала, но которые хотят знать принцип достижения надежности. Для быстрого запуска используйте клиентский пакет SDK.

Инициализация

Чтобы использовать надежные подпротоколы, необходимо задать подпротокол при создании подключений Websocket. В JavaScript можно использовать следующий код:

  • Используйте надежный подпротокол JSON:

    var pubsub = new WebSocket(
      "wss://test.webpubsub.azure.com/client/hubs/hub1",
      "json.reliable.webpubsub.azure.v1"
    );
    
  • Используйте надежный подпротокол Protobuf:

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

Восстановление подключения

Подключение восстановление является основой достижения надежности и должно быть реализовано при использовании json.reliable.webpubsub.azure.v1 и protobuf.reliable.webpubsub.azure.v1 протоколах.

Подключения Websocket полагаются на TCP. Если подключение не упадет, сообщения не будут потеряны и доставлены по порядку. Чтобы предотвратить потерю сообщений по удаленным подключениям, служба Web PubSub сохраняет сведения о состоянии подключения, включая сведения о группе и сообщении. Эта информация используется для восстановления клиента при восстановлении подключения.

Когда клиент повторно подключается к службе с помощью надежных подпротоколов, клиент получит Connected сообщение, connectionId содержащее и reconnectionToken. Определяет connectionId сеанс подключения в службе.

{
  "type": "system",
  "event": "connected",
  "connectionId": "<connection_id>",
  "reconnectionToken": "<reconnection_token>"
}

После удаления подключения WebSocket клиент должен попытаться повторно подключиться к тому же, чтобы восстановить тот же connectionId сеанс. Клиентам не нужно вести переговоры с сервером и получать их access_token. Вместо этого, чтобы восстановить подключение, клиент должен сделать запрос на подключение WebSocket непосредственно к службе с именем узла службы иconnection_idreconnection_token:

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

восстановление Подключение ion может завершиться ошибкой, если проблема с сетью еще не была восстановлена. Клиент должен повторить попытку повторного подключения до тех пор, пока не будет выполняться следующее:

  1. Подключение Websocket закрыто с кодом состояния 1008. Код состояния означает, что идентификатор подключения удален из службы.
  2. Сбой восстановления продолжается более 1 минуты.

Издатель

Клиенты, отправляющие события обработчикам событий или публикующие сообщения другим клиентам, называются издателями. Издатели должны задать ackId в сообщении подтверждение от службы Web PubSub, что публикация сообщения была успешной или нет.

Это ackId идентификатор сообщения, каждое новое сообщение должно использовать уникальный идентификатор. Исходный ackId объект следует использовать при повторной отправке сообщения.

Пример сообщения о отправке группы:

{
  "type": "sendToGroup",
  "group": "group1",
  "dataType": "text",
  "data": "text data",
  "ackId": 1
}

Пример ответа на ack:

{
  "type": "ack",
  "ackId": 1,
  "success": true
}

Когда служба Web PubSub возвращает ответ ack, success: trueсообщение обрабатывается службой, и клиент может ожидать, что сообщение будет доставлено всем подписчикам.

Когда служба испытывает временную внутреннюю ошибку, и сообщение не может быть отправлено подписчику, издатель получит ack с success: false. Издатель должен прочитать ошибку, чтобы определить, следует ли повторно отправить сообщение. Если сообщение обижается, то же ackId самое следует использовать.

{
  "type": "ack",
  "ackId": 1,
  "success": false,
  "error": {
    "name": "InternalServerError",
    "message": "Internal server error"
  }
}

Message Failure

Если ответ на ошибку службы потерян, так как подключение WebSocket удалено, издатель должен повторно отправить сообщение с тем же ackId сообщением после восстановления. Когда сообщение было обработано службой ранее, оно отправит сообщение, содержащее ошибку Duplicate . Издатель должен прекратить повторное выполнение этого сообщения.

{
  "type": "ack",
  "ackId": 1,
  "success": false,
  "error": {
    "name": "Duplicate",
    "message": "Message with ack-id: 1 has been processed"
  }
}

Message duplicated

Подписчик

Клиенты, получающие сообщения от обработчиков событий или издателей, называются подписчиками. При удалении подключений из-за проблем с сетью служба Web PubSub не знает, сколько сообщений было отправлено подписчикам. Чтобы определить последнее сообщение, полученное подписчиком, служба отправляет сообщение с данными, содержащее сообщение sequenceId. Подписчик отвечает с сообщением о последовательности:

Пример последовательности:

{
  "type": "sequenceAck",
  "sequenceId": 1
}

Это sequenceId добавочное число uint64 в сеансе идентификатора подключения. Подписчики должны записывать наибольшее sequenceId полученное сообщение, принимать только сообщения с большим sequenceIdразмером и удалять сообщения с меньшим или равным sequenceId. Подписчик должен взломать с наибольшим sequenceId записанным, чтобы служба может пропустить повторное удаление сообщений, которые уже получили подписчики. Например, если подписчик отвечает на sequenceAcksequenceId: 5запрос, служба будет повторно отправить сообщения с sequenceId размером более 5.

Все сообщения доставляются подписчикам, пока подключение WebSocket не удаляется. С помощью sequenceIdслужбы можно узнать, сколько подписчиков получили через подключения WebSocket в сеансе. После удаления подключения WebSocket служба будет повторно удалять сообщения, не подтвержденные подписчиком. Служба сохраняет ограниченное количество незамеченных сообщений. Если количество сообщений превышает ограничение, служба закроет подключение WebSocket и удалите сеанс. Таким образом, подписчики должны взломать как можно скорее sequenceId .