Creación de WebSocket de confianza con un subprotocolo

Cuando las conexiones de cliente de Websocket se quitan debido a problemas de red intermitentes, se pueden perder mensajes. En un sistema pub/sub, los publicadores se desacoplan de los suscriptores, por lo que es posible que los editores no detecten la conexión o pérdida de mensajes descartadas de los suscriptores. Es fundamental que los clientes superen los problemas de red intermitentes y mantengan una entrega confiable de mensajes. Para lograrlo, puede crear un cliente de Websocket confiable con la ayuda de subprotocolos de Azure Web PubSub confiables.

Protocolo de confianza

El servicio Web PubSub admite dos subprotocolos json.reliable.webpubsub.azure.v1 confiables y protobuf.reliable.webpubsub.azure.v1. Los clientes deben seguir las partes de publicador, suscriptor y recuperación del subprotocolo para lograr confiabilidad. Si no se implementa correctamente el subprotocolo, la entrega del mensaje no funciona según lo esperado o el servicio que termina el cliente debido a infracciones del protocolo.

La manera sencilla: uso del SDK de cliente

La manera más sencilla de crear un cliente confiable es usar el SDK de cliente. El SDK de cliente implementa la especificación de cliente de Web PubSub y usa json.reliable.webpubsub.azure.v1 de forma predeterminada. Consulte Publicación o suscripción entre clientes para obtener un inicio rápido.

The Hard Way - Implement by hand

El siguiente tutorial le guía por la parte importante de la implementación de la especificación del cliente de Web PubSub. Esta guía no es para las personas que buscan un inicio rápido, pero que quiere conocer el principio de lograr la confiabilidad. Para obtener un inicio rápido, use el SDK de cliente.

Inicialización

Para usar subprotocolos confiables, debe establecer el subprotocolo al construir conexiones de Websocket. En JavaScript, puede usar el código siguiente:

  • Use el subprotocolo confiable de Json:

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

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

Recuperación de conexión

Conectar recuperación es la base de lograr la confiabilidad y debe implementarse al usar los json.reliable.webpubsub.azure.v1 protocolos y protobuf.reliable.webpubsub.azure.v1 .

Las conexiones de Websocket dependen de TCP. Cuando la conexión no se quita, los mensajes no se pierden y se entregan en orden. Para evitar la pérdida de mensajes en conexiones eliminadas, el servicio Web PubSub conserva la información de estado de conexión, incluida la información de grupo y mensaje. Esta información se usa para restaurar el cliente en la recuperación de la conexión.

Cuando el cliente se vuelve a conectar al servicio mediante subprotocolos confiables, el cliente recibirá un Connected mensaje que contiene y reconnectionTokenconnectionId . connectionId identifica la sesión de la conexión en el servicio.

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

Una vez que se quita la conexión de WebSocket, el cliente debe intentar volver a conectarse con el mismo connectionId para restaurar la misma sesión. Los clientes no necesitan negociar con el servidor y obtener .access_token En su lugar, para recuperar la conexión, el cliente debe realizar una solicitud de conexión de WebSocket directamente al servicio con el nombre de host del servicio, connection_idy reconnection_token:

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

es posible que se produzca un error en la recuperación de Conectar ion si aún no se ha recuperado el problema de red. El cliente debe seguir intentando volver a conectarse hasta que:

  1. La conexión de Websocket se cierra con el código de estado 1008. El código de estado significa que la propiedad connectionId se ha quitado del servicio.
  2. Se sigue produciendo un error de recuperación durante más de 1 minuto.

Publicador

Los clientes que envían eventos a controladores de eventos o publican mensajes en otros clientes se denominan publicadores. Los publicadores deben establecer ackId en el mensaje para recibir una confirmación del servicio Web PubSub que publica el mensaje correctamente o no.

ackId es el identificador del mensaje, cada mensaje nuevo debe usar un identificador único. El original ackId debe usarse al volver a enviar un mensaje.

Ejemplo de un mensaje que se envía a un grupo:

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

Ejemplo de una respuesta de confirmación:

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

Cuando el servicio Web PubSub devuelve una respuesta de confirmación con success: true, el servicio procesa el mensaje y el cliente puede esperar que el mensaje se entregue a todos los suscriptores.

Cuando el servicio experimenta un error interno transitorio y el mensaje no se puede enviar al suscriptor, el publicador recibirá una confirmación con success: false. El publicador debe leer el error para determinar si se va a volver a enviar el mensaje. Si el mensaje se vuelve a enviar, se debe usar el mismo ackId .

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

Message Failure

Si se pierde la respuesta de confirmación del servicio porque se quitó la conexión de WebSocket, el publicador debe volver a enviar el mensaje con el mismo ackId después de la recuperación. Cuando el servicio procesó previamente el mensaje, enviará una confirmación que contiene un Duplicate error. El publicador debe dejar de enviar este mensaje.

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

Message duplicated

Suscriptor

Los clientes que reciben mensajes de controladores de eventos o publicadores se denominan suscriptores. Cuando las conexiones se quitan debido a problemas de red, el servicio Web PubSub no sabe cuántos mensajes se enviaron a los suscriptores. Para determinar el último mensaje recibido por el suscriptor, el servicio envía un mensaje de datos que contiene un sequenceId. El suscriptor responde con un mensaje de confirmación de secuencia:

Ejemplo de confirmación de secuencia:

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

sequenceId es un número incremental de uint64 en una sesión de identificador de conexión. Los suscriptores deben registrar el mayor que sequenceId ha recibido, aceptar solo los mensajes con un mayor sequenceIdy quitar mensajes con un menor o igual sequenceId. El suscriptor debe tener la sequenceId mayor cantidad de registros, de modo que el servicio pueda omitir los mensajes de reeivering que ya han recibido los suscriptores. Por ejemplo, si el suscriptor responde con un sequenceAck con sequenceId: 5, el servicio solo volverá a enviar mensajes con un sequenceId valor superior a 5.

Todos los mensajes se entregan a los suscriptores en orden hasta que se quita la conexión de WebSocket. Con sequenceId, el servicio puede saber cuántos mensajes han recibido los suscriptores en las conexiones de WebSocket en una sesión. Después de quitar una conexión de WebSocket, el servicio rehacerá los mensajes no confirmados por el suscriptor. El servicio almacena un número limitado de mensajes no reconocidos. Cuando el número de mensajes supera el límite, el servicio cerrará la conexión de WebSocket y quitará la sesión. Por lo tanto, los suscriptores deben realizar la confirmación lo sequenceId antes posible.