Создание надежного 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_id
reconnection_token
:
wss://<service-endpoint>/client/hubs/<hub>?awps_connection_id=<connection_id>&awps_reconnection_token=<reconnection_token>
Восстановление подключения может завершиться ошибкой, если проблема с сетью еще не восстановлена. Клиент должен повторить попытку повторного подключения до тех пор, пока не будет выполняться следующее:
- Подключение WebSocket закрыто с кодом состояния 1008. Код состояния означает, что идентификатор подключения удален из службы.
- Сбой восстановления продолжается более 1 минуты.
Publisher
Клиенты, отправляющие события обработчикам событий или публикующие сообщения другим клиентам, называются издателями. Издатели должны задать 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"
}
}
Если ответ на ошибку службы потерян, так как подключение WebSocket удалено, издатель должен повторно отправить сообщение с тем же ackId
сообщением после восстановления. Когда сообщение было обработано службой ранее, оно отправит сообщение, содержащее ошибку Duplicate
. Издатель должен прекратить повторное выполнение этого сообщения.
{
"type": "ack",
"ackId": 1,
"success": false,
"error": {
"name": "Duplicate",
"message": "Message with ack-id: 1 has been processed"
}
}
Подписчик
Клиенты, получающие сообщения от обработчиков событий или издателей, называются подписчиками. При удалении подключений из-за проблем с сетью служба Web PubSub не знает, сколько сообщений было отправлено подписчикам. Чтобы определить последнее сообщение, полученное подписчиком, служба отправляет сообщение с данными, содержащее сообщение sequenceId
. Подписчик отвечает с сообщением о последовательности:
Пример последовательности:
{
"type": "sequenceAck",
"sequenceId": 1
}
Это sequenceId
добавочное число uint64 в сеансе идентификатора подключения. Подписчики должны записывать наибольшее sequenceId
полученное сообщение, принимать только сообщения с большим sequenceId
размером и удалять сообщения с меньшим или равным sequenceId
. Подписчик должен взломать с наибольшим sequenceId
записанным, чтобы служба может пропустить повторное удаление сообщений, которые уже получили подписчики. Например, если подписчик отвечает на sequenceAck
sequenceId: 5
запрос, служба будет повторно отправить сообщения с sequenceId
размером более 5.
Все сообщения доставляются подписчикам, пока подключение WebSocket не удаляется. С помощью sequenceId
службы можно узнать, сколько подписчиков получили через подключения WebSocket в сеансе. После удаления подключения WebSocket служба будет повторно удалять сообщения, не подтвержденные подписчиком. Служба сохраняет ограниченное количество незамеченных сообщений. Если количество сообщений превышает ограничение, служба закроет подключение WebSocket и удалите сеанс. Таким образом, подписчики должны взломать как можно скорее sequenceId
.