Crie Websocket confiável com subprotocolo

Quando as conexões do cliente Websocket caem devido a problemas intermitentes de rede, as mensagens podem ser perdidas. Em um pub/subsistema, os editores são dissociados dos assinantes, portanto, os editores podem não detetar a perda de conexão ou mensagem de um assinante. É crucial que os clientes superem problemas intermitentes de rede e mantenham uma entrega de mensagens confiável. 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 suporta dois subprotocolos json.reliable.webpubsub.azure.v1 confiáveis e protobuf.reliable.webpubsub.azure.v1. Os clientes devem seguir as partes do editor, assinante e recuperação do subprotocolo para obter confiabilidade. A falha na implementação correta do subprotocolo pode resultar na entrega de mensagens não funcionar como esperado ou no encerramento do serviço do cliente devido a violações de protocolo.

A maneira 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. Por favor, consulte Publicar /subscrever entre os clientes para um início rápido.

The Hard Way - Implemente à mão

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 querem saber 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 Protobuf:

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

Recuperação de 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 sem perdas e entregues em ordem. Para evitar a perda de mensagens em conexões interrompidas, 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 reconecta 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>"
}

Uma vez que a conexão WebSocket cai, o cliente deve 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. Em vez disso, para recuperar a conexão, o cliente deve fazer uma solicitação de conexão WebSocket diretamente ao serviço com o nome do host do serviço, connection_ide reconnection_token:

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

A recuperação da conexão pode falhar se o problema de rede ainda não tiver sido recuperado. O cliente deve continuar tentando se reconectar até:

  1. A conexão Websocket é fechada com o código de status 1008. O código de status significa que o connectionId foi removido do serviço.
  2. Uma falha de recuperação continua a ocorrer por mais de 1 minuto.

Editor

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 na 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.

Um exemplo de mensagem de envio de grupo:

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

Um exemplo de resposta ack:

{
  "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 tiver 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, o mesmo ackId deve ser usado.

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

Message Failure

Se a resposta ack do serviço for perdida porque a conexão WebSocket caiu, o editor deve 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 esta mensagem.

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

Message duplicated

Subscritor

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 sequenceIdarquivo . O assinante responde com uma sequência ack mensagem:

Uma sequência de amostra ack:

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

O sequenceId é um número incremental uint64 em uma sessão de ID de conexão. Os assinantes devem gravar o maior que recebeu, aceitar apenas mensagens com um maior sequenceIdsequenceId, e soltar mensagens com um menor ou igual sequenceId. O assinante deve contar com o maior sequenceId que registrou, para que o serviço possa pular a reentrega de mensagens que os assinantes já receberam. Por exemplo, se o assinante responder com um com , o serviço só reenviará mensagens com sequenceId: 5um sequenceAcksequenceId maior que 5.

Todas as mensagens são entregues aos assinantes em ordem até que a conexão WebSocket caia. Com sequenceIdo , o serviço pode saber quantas mensagens os assinantes receberam em conexões WebSocket em uma sessão. Depois que uma conexão WebSocket cair, o serviço entregará novamente mensagens não reconhecidas pelo assinante. O serviço armazena um número limitado de mensagens não reconhecidas. Quando o número de mensagens exceder o limite, o serviço fechará a conexão WebSocket e removerá a sessão. Assim, os subscritores devem ack o sequenceId mais rapidamente possível.