Crie websocket fiável com subprotocol

As ligações do cliente websocket podem cair devido a problemas de rede intermitentes e quando as ligações caírem, as mensagens também serão perdidas. Num sistema pubsub, as editoras são dissociadas dos assinantes, pelo que as editoras são difíceis de detetar a queda de subscritores ou a perda de mensagens. É crucial para os clientes superarem o problema de rede intermitente e manterem a fiabilidade da entrega de mensagens. Para isso, pode criar um cliente Websocket confiável com a ajuda de subprotocols fiáveis.

Nota

Protocolos fiáveis ainda estão em pré-visualização. Esperam-se algumas mudanças no futuro.

Protocolo fiável

O serviço suporta dois subprotocols json.reliable.webpubsub.azure.v1 fiáveis e protobuf.reliable.webpubsub.azure.v1. Os clientes devem seguir o protocolo, incluindo principalmente a parte da reconexão, editor e assinante para obter a fiabilidade, ou a entrega de mensagens pode não funcionar como esperado ou o serviço pode rescindir o cliente uma vez que viola a especificação do protocolo.

Inicialização

Para utilizar subprotocols fiáveis, deve definir subprotocol ao construir ligações Websocket. No JavaScript, pode utilizar como seguinte:

  • Use subprotocol Json fiável

    var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'json.reliable.webpubsub.azure.v1');
    
  • Utilize subprotocol protobuf fiável

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

Reconexão

As ligações websocket retransmitimem no TCP, por isso, se a ligação não cair, todas as mensagens devem ser sem perdas e em ordem. Quando confrontados com problemas de rede e ligações caem, todo o estado como informações de grupo e de mensagens são mantidos pelo serviço e aguardam a reconexão para recuperar. Uma ligação Websocket é proprietária de uma sessão no serviço e o identificador é connectionId. A reconexão é a base para a fiabilidade e deve ser implementada. Quando uma nova ligação se ligar ao serviço utilizando subprotocols fiáveis, a ligação receberá uma Connected mensagem e connectionIdreconnectionToken.

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

Uma vez que a ligação WebSocket caiu, o cliente deve primeiro tentar reconectar-se com o mesmo connectionId para manter a sessão. Os clientes não precisam de negociar com o servidor e obter o access_token. Em vez disso, a reconexão deve fazer um pedido de ligação websocket ao serviço diretamente com connection_id e reconnection_token com os seguintes uri:

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

A reconexão pode falhar, uma vez que o problema da rede ainda não foi recuperado. O cliente deve continuar a tentar reconectar-se até

  1. Ligação websocket fechada com o código de estado 1008. O código de estado significa que a ligaçãoId foi removida do serviço.
  2. A falha de reconexão mantém-se mais de 1 minuto.

Publisher

Os clientes que enviam eventos para o manipulador de eventos ou publicam mensagem a outros clientes são chamados editores no documento. Os editores devem definir ackId a mensagem para ser reconhecido pelo serviço sobre se a mensagem publica o sucesso ou não. A ackId mensagem na mensagem é o identificador da mensagem, o que significa que mensagens diferentes devem usar diferentes ackIds, enquanto a mensagem de reencamamento deve manter o mesmo ackId para o serviço des duplicado.

Um grupo de amostras envia mensagem:

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

Uma resposta de amostra ack:

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

Se o serviço voltar a funcionar, success: truea mensagem foi processada pelo serviço e o cliente pode esperar que a mensagem seja entregue a todos os assinantes.

No entanto, em alguns casos, o Serviço encontra algum erro interno transitório e a mensagem não pode ser enviada para assinante. Nesse caso, a editora receberá uma mensagem como seguir e deve reencaixar a mensagem com a mesma ackId se for necessária com base na lógica de negócio.

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

Message Failure

O serviço pode ser abandonado devido à ligação WebSockets ter caído. Assim, os editores devem ser notificados quando a ligação Websocket cair e reencamender a mensagem com a mesma ackId após a reconexão. Se a mensagem tiver realmente sido processada pelo serviço, irá responder ack com Duplicate e os editores devem parar de reencaender esta mensagem novamente.

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

Message duplicated

Assinante

Os clientes que recebem mensagens enviadas de manipuladores de eventos ou editores são chamados de assinante no documento. Quando as ligações deixam de ser por problemas de rede, o serviço não sabe quantas mensagens são realmente enviadas para os assinantes. Assim, os assinantes devem dizer ao serviço que mensagem foi recebida. As mensagens de dados contêm sequenceId e os assinantes devem ack o id de sequência com a mensagem ack de sequência:

Uma sequência de amostra ack:

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

O id de sequência é um número incremental uint64 com uma sessão de id de ligação. Os assinantes devem registar o maior id de sequência que já recebeu e aceitar todas as mensagens com id de sequência maior e deixar cair todas as mensagens com id de sequência menor ou igual. A sequência ack suporta ack cumulativa, o que significa que se você ack sequence-id=5, o serviço irá tratar todas as mensagens com id de sequência inferior a 5 já foram recebidas por assinantes. Os subscritores deverão encontrar o maior id de sequência que registou, para que o serviço possa saltar para reenvirar mensagens que os assinantes já receberam.

Todas as mensagens são entregues aos assinantes por ordem até que a ligação WebSockets caia. Com o id de sequência, o serviço pode ter o conhecimento de quantas mensagens os assinantes receberam através de ligações WebSockets com uma sessão de id de ligação. Após a queda de uma ligação WebSockets, o serviço irá reaquecê-las mensagens que deve entregar, mas não ack-ed pelo assinante. O serviço retém mensagens que não são ack-ed com limite, se as mensagens excederem o limite, o serviço fechará a ligação WebSockets e removerá a sessão de id de ligação. Assim, os subscritores devem ack ad a sequência id o mais rapidamente possível.