Creare reliable Websocket con subprotocol

Quando le connessioni client Websocket vengono interrotte a causa di problemi di rete intermittenti, i messaggi possono andare persi. In un sistema pub/secondario i server di pubblicazione sono separati dai sottoscrittori, pertanto gli editori potrebbero non rilevare la connessione o la perdita di messaggi di un sottoscrittore. È fondamentale che i client superino i problemi di rete intermittenti e mantengano il recapito affidabile dei messaggi. A tale scopo, è possibile creare un client Websocket affidabile con l'aiuto di sottoprotocoli Web PubSub di Azure affidabili.

Reliable Protocol

Il servizio Web PubSub supporta due sottoprotocols json.reliable.webpubsub.azure.v1 affidabili e protobuf.reliable.webpubsub.azure.v1. I client devono seguire le parti di pubblicazione, sottoscrittore e ripristino del sottoprotocolo per ottenere l'affidabilità. Se non si implementa correttamente il sottoprotocolo, il recapito del messaggio non funziona come previsto o il servizio termina il client a causa di violazioni del protocollo.

Il modo semplice - Usare l'SDK client

Il modo più semplice per creare un client affidabile consiste nell'usare Client SDK. Client SDK implementa la specifica del client Web PubSub e usa per json.reliable.webpubsub.azure.v1 impostazione predefinita. Per una guida introduttiva, vedere Pubblicare/sottoscrivere i client .

Il modo difficile - Implementare a mano

L'esercitazione seguente illustra la parte importante dell'implementazione della specifica client Web PubSub. Questa guida non è destinata alle persone che cercano un avvio rapido, ma che vogliono conoscere il principio di raggiungimento dell'affidabilità. Per una guida introduttiva, usare l'SDK client.

Inizializzazione

Per usare sottoprotocoli affidabili, è necessario impostare il sottoprotocolo durante la creazione di connessioni Websocket. In JavaScript è possibile usare il codice seguente:

  • Usare il sottoprotocolo Reliable Json:

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

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

Ripristino delle connessioni

Connessione ripristino è la base per ottenere l'affidabilità e deve essere implementata quando si usano i json.reliable.webpubsub.azure.v1 protocolli e protobuf.reliable.webpubsub.azure.v1 .

Le connessioni Websocket si basano su TCP. Quando la connessione non viene rilasciata, i messaggi sono senza perdita e recapitati in ordine. Per evitare la perdita di messaggi sulle connessioni eliminate, il servizio Web PubSub mantiene le informazioni sullo stato della connessione, incluse le informazioni sul gruppo e sui messaggi. Queste informazioni vengono usate per ripristinare il client in caso di ripristino della connessione

Quando il client si riconnette al servizio usando sottoprotocols reliable, il client riceverà un Connected messaggio contenente e connectionIdreconnectionToken. Identifica connectionId la sessione della connessione nel servizio.

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

Quando la connessione WebSocket viene eliminata, il client deve provare a riconnettersi con lo stesso connectionId per ripristinare la stessa sessione. I client non devono negoziare con il server e ottenere .access_token Per ripristinare la connessione, invece, il client deve effettuare una richiesta di connessione WebSocket direttamente al servizio con il nome host del servizio, connection_ide reconnection_token:

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

Connessione ripristino potrebbe non riuscire se il problema di rete non è stato ancora recuperato. Il client deve continuare a riprovare a riconnettersi fino a quando:

  1. La connessione Websocket viene chiusa con il codice di stato 1008. Il codice di stato indica che connectionId è stato rimosso dal servizio.
  2. Un errore di ripristino continua a verificarsi per più di 1 minuto.

Autore

I client che inviano eventi ai gestori eventi o pubblicano messaggi in altri client vengono chiamati server di pubblicazione. I server di pubblicazione devono essere impostati ackId nel messaggio per ricevere un riconoscimento dal servizio Web PubSub che pubblica il messaggio è riuscito o meno.

ackId è l'identificatore del messaggio, ogni nuovo messaggio deve usare un ID univoco. L'originale ackId deve essere usato quando si invia nuovamente un messaggio.

Messaggio di invio di un gruppo di esempio:

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

Risposta ack di esempio:

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

Quando il servizio Web PubSub restituisce una risposta ack con success: true, il messaggio è stato elaborato dal servizio e il client può aspettarsi che il messaggio venga recapitato a tutti i sottoscrittori.

Quando il servizio riscontra un errore interno temporaneo e il messaggio non può essere inviato al sottoscrittore, il server di pubblicazione riceverà un ack con success: false. L'autore deve leggere l'errore per determinare se inviare nuovamente il messaggio. Se il messaggio viene reinviato, deve essere usato lo stesso ackId .

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

Message Failure

Se la risposta ack del servizio viene persa perché la connessione WebSocket è stata eliminata, l'autore deve inviare nuovamente il messaggio con lo stesso ackId risultato dopo il ripristino. Quando il messaggio è stato elaborato in precedenza dal servizio, invierà un ack contenente un Duplicate errore. Il server di pubblicazione deve smettere di inviare nuovamente il messaggio.

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

Message duplicated

Sottoscrittore

I client che ricevono messaggi dai gestori eventi o dai server di pubblicazione vengono chiamati sottoscrittori. Quando le connessioni diminuiscono a causa di problemi di rete, il servizio Web PubSub non conosce il numero di messaggi inviati ai sottoscrittori. Per determinare l'ultimo messaggio ricevuto dal sottoscrittore, il servizio invia un messaggio di dati contenente un oggetto sequenceId. Il sottoscrittore risponde con un messaggio sequence ack:

Ack sequenza di esempio:

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

sequenceId è un numero incrementale uint64 in una sessione connection-id. I Sottoscrittori devono registrare il più grande sequenceId ricevuto, accettare solo i messaggi con un maggiore sequenceIde rilasciare messaggi con un valore minore o uguale sequenceIda . Il sottoscrittore deve avere il valore più grande sequenceId registrato, in modo che il servizio possa ignorare i messaggi di rollforward già ricevuti dai sottoscrittori. Ad esempio, se il sottoscrittore risponde con un sequenceAck con sequenceId: 5, il servizio invierà di nuovo solo i messaggi con un sequenceId valore maggiore di 5.

Tutti i messaggi vengono recapitati ai sottoscrittori in ordine fino a quando la connessione WebSocket non viene eliminata. Con sequenceId, il servizio può conoscere il numero di sottoscrittori di messaggi ricevuti tra connessioni WebSocket in una sessione. Dopo l'eliminazione di una connessione WebSocket, il servizio rieligherà i messaggi non riconosciuti dal sottoscrittore. Il servizio archivia un numero limitato di messaggi non riconosciuti. Quando il numero di messaggi supera il limite, il servizio chiuderà la connessione WebSocket e rimuoverà la sessione. Pertanto, i sottoscrittori dovrebbero ack il sequenceId prima possibile.