Crie WebSocket confiável com subprotocolo
Quando as conexões de cliente WebSocket são descartadas devido a problemas de rede intermitentes, as mensagens podem ser perdidas. Em um sistema pub/sub, os editores são dissociados dos assinantes, portanto, os editores podem não detectar a queda de conexão ou a perda de mensagens de um assinante. É crucial que os clientes superem problemas de rede intermitentes e mantenham a entrega confiável de mensagens. Para conseguir isso, você pode criar um cliente WebSocket confiável com a ajuda de subprotocolos confiáveis do Azure Web PubSub.
Protocolo confiável
O serviço Web PubSub oferece suporte a dois subprotocolos json.reliable.webpubsub.azure.v1
confiáveis e protobuf.reliable.webpubsub.azure.v1
. Os clientes devem seguir as partes do editor, do assinante e da recuperação do subprotocolo para obter confiabilidade. A falha na implementação adequada do subprotocolo pode fazer com que a entrega da mensagem não funcione conforme o esperado ou o serviço encerre o cliente devido a violações de protocolo.
A maneira mais fácil - Use o SDK do cliente
A maneira mais simples de criar um cliente confiável é usar o SDK do cliente. O SDK do cliente implementa a especificação do cliente Web PubSub e usa json.reliable.webpubsub.azure.v1
por padrão. Consulte Publicar/assinar entre clientes para iniciar rapidamente.
A maneira mais difícil - Implemente manualmente
O tutorial a seguir orienta você pela parte importante da implementação da especificação do cliente Web PubSub. Este guia não é para pessoas que procuram um início rápido, mas que desejam conhecer o princípio de alcançar a confiabilidade. Para um início rápido, use o SDK do cliente.
Inicialização
Para usar subprotocolos confiáveis, você deve definir o subprotocolo ao construir conexões WebSocket. Em JavaScript, você pode usar o seguinte código:
Use o subprotocolo confiável Json:
var pubsub = new WebSocket( "wss://test.webpubsub.azure.com/client/hubs/hub1", "json.reliable.webpubsub.azure.v1" );
Use o subprotocolo confiável do Protobuf:
var pubsub = new WebSocket( "wss://test.webpubsub.azure.com/client/hubs/hub1", "protobuf.reliable.webpubsub.azure.v1" );
Recuperação da conexão
A recuperação de conexão é a base para alcançar a confiabilidade e deve ser implementada ao usar os json.reliable.webpubsub.azure.v1
protocolos e protobuf.reliable.webpubsub.azure.v1
.
As conexões WebSocket dependem do TCP. Quando a conexão não cai, as mensagens são entregues sem perdas e em ordem. Para evitar a perda de mensagens em conexões descartadas, o serviço Web PubSub retém as informações de status da conexão, incluindo informações de grupo e mensagem. Essas informações são usadas para restaurar o cliente na recuperação da conexão
Quando o cliente se reconectar ao serviço usando subprotocolos confiáveis, o cliente receberá uma Connected
mensagem contendo o connectionId
e reconnectionToken
. O connectionId
identifica a sessão da conexão no serviço.
{
"type": "system",
"event": "connected",
"connectionId": "<connection_id>",
"reconnectionToken": "<reconnection_token>"
}
Depois que a conexão WebSocket cair, o cliente deverá tentar se reconectar com o mesmo connectionId
para restaurar a mesma sessão. Os clientes não precisam negociar com o servidor e obter o access_token
arquivo . Em vez disso, para recuperar a conexão, o cliente deve fazer uma solicitação de conexão WebSocket diretamente para o serviço com o nome do host do serviço, connection_id
e reconnection_token
:
wss://<service-endpoint>/client/hubs/<hub>?awps_connection_id=<connection_id>&awps_reconnection_token=<reconnection_token>
A recuperação de conexão pode falhar se o problema de rede ainda não tiver sido recuperado. O cliente deve continuar tentando se reconectar até que:
- A conexão WebSocket é fechada com o código de status 1008. O código de status significa que a ConnectionID foi removida do serviço.
- Uma falha de recuperação continua a ocorrer por mais de 1 minuto.
Publicador
Os clientes que enviam eventos para manipuladores de eventos ou publicam mensagens para outros clientes são chamados de editores. Os editores devem definir ackId
a mensagem para receber uma confirmação do serviço Web PubSub de que a publicação da mensagem foi bem-sucedida ou não.
O ackId
é o identificador da mensagem, cada nova mensagem deve usar um ID exclusivo. O original ackId
deve ser usado ao reenviar uma mensagem.
Uma mensagem de envio de grupo de exemplo:
{
"type": "sendToGroup",
"group": "group1",
"dataType": "text",
"data": "text data",
"ackId": 1
}
Uma resposta ACK de exemplo:
{
"type": "ack",
"ackId": 1,
"success": true
}
Quando o serviço Web PubSub retorna uma resposta ack com success: true
, a mensagem foi processada pelo serviço e o cliente pode esperar que a mensagem seja entregue a todos os assinantes.
Quando o serviço apresentar um erro interno transitório e a mensagem não puder ser enviada ao assinante, o editor receberá um ack com success: false
. O editor deve ler o erro para determinar se deve ou não reenviar a mensagem. Se a mensagem for reenviada, a mesma ackId
deve ser usada.
{
"type": "ack",
"ackId": 1,
"success": false,
"error": {
"name": "InternalServerError",
"message": "Internal server error"
}
}
Se a resposta de confirmação do serviço for perdida porque a conexão WebSocket caiu, o editor deverá reenviar a mensagem com a mesma ackId
após a recuperação. Quando a mensagem foi processada anteriormente pelo serviço, ele enviará um ack contendo um Duplicate
erro. O editor deve parar de reenviar essa mensagem.
{
"type": "ack",
"ackId": 1,
"success": false,
"error": {
"name": "Duplicate",
"message": "Message with ack-id: 1 has been processed"
}
}
Assinante
Os clientes que recebem mensagens de manipuladores de eventos ou editores são chamados de assinantes. Quando as conexões caem devido a problemas de rede, o serviço Web PubSub não sabe quantas mensagens foram enviadas aos assinantes. Para determinar a última mensagem recebida pelo assinante, o serviço envia uma mensagem de dados contendo um sequenceId
arquivo . O assinante responde com uma mensagem de confirmação de sequência:
Uma confirmação de sequência de exemplo:
{
"type": "sequenceAck",
"sequenceId": 1
}
O sequenceId
é um número incremental uint64 em uma sessão de ID de conexão. Os assinantes devem registrar o maior sequenceId
que recebeu, aceitar apenas mensagens com um maior sequenceId
, e descartar mensagens com um menor ou igual sequenceId
. O assinante deve aceitar o maior sequenceId
que registrou, para que o serviço possa ignorar a reentrega de mensagens que os assinantes já receberam. Por exemplo, se o assinante responder com um sequenceAck
with sequenceId: 5
, o serviço só reenviará mensagens com um sequenceId
maior que 5.
Todas as mensagens são entregues aos assinantes em ordem até que a conexão WebSocket caia. Com sequenceId
o , o serviço pode saber quantas mensagens os assinantes receberam em conexões WebSocket em uma sessão. Depois que uma conexão WebSocket for interrompida, o serviço entregará novamente as mensagens não confirmadas pelo assinante. O serviço armazena um número limitado de mensagens não confirmadas. Quando o número de mensagens exceder o limite, o serviço fechará a conexão WebSocket e removerá a sessão. Assim, os assinantes devem ackar o sequenceId
mais rápido possível.