Skapa tillförlitlig Websocket med subprotocol

När Websocket-klientanslutningar tas bort på grund av tillfälliga nätverksproblem kan meddelanden gå förlorade. I ett pub-/undersystem frikopplas utgivare från prenumeranter, så utgivare kanske inte identifierar en prenumerants borttagna anslutning eller meddelandeförlust. Det är viktigt för klienter att lösa tillfälliga nätverksproblem och upprätthålla tillförlitlig meddelandeleverans. För att uppnå detta kan du skapa en tillförlitlig Websocket-klient med hjälp av tillförlitliga Azure Web PubSub-underprotokoler.

Reliable Protocol

Web PubSub-tjänsten stöder två tillförlitliga subprotocols json.reliable.webpubsub.azure.v1 och protobuf.reliable.webpubsub.azure.v1. Klienter måste följa utgivar-, prenumerant- och återställningsdelarna i delprotokolen för att uppnå tillförlitlighet. Om subprotokolen inte implementeras korrekt kan det leda till att meddelandeleveransen inte fungerar som förväntat eller att tjänsten avslutar klienten på grund av protokollöverträdelser.

Det enkla sättet – Använda klient-SDK

Det enklaste sättet att skapa en tillförlitlig klient är att använda Client SDK. Klient-SDK implementerar Web PubSub-klientspecifikation och använder json.reliable.webpubsub.azure.v1 som standard. Se Publicera/prenumerera bland klienter för snabbstart.

Den hårda vägen – Implementera för hand

I följande självstudie går vi igenom den viktiga delen av implementeringen av Web PubSub-klientspecifikationen. Den här guiden är inte till för personer som vill ha en snabbstart utan som vill veta principen om att uppnå tillförlitlighet. Använd klient-SDK:t för snabbstart.

Initiering

Om du vill använda tillförlitliga subprotokoler måste du ange delprotokolen när du skapar Websocket-anslutningar. I JavaScript kan du använda följande kod:

  • Använd Json reliable subprotocol:

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

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

Anslut ion-återställning

Anslut ion recovery är grunden för att uppnå tillförlitlighet och måste implementeras när du använder protokollen json.reliable.webpubsub.azure.v1 och protobuf.reliable.webpubsub.azure.v1 .

Websocket-anslutningar förlitar sig på TCP. När anslutningen inte tas bort blir meddelandena förlustfria och levereras i ordning. För att förhindra meddelandeförlust över borttagna anslutningar behåller Web PubSub-tjänsten informationen om anslutningsstatus, inklusive grupp- och meddelandeinformation. Den här informationen används för att återställa klienten vid anslutningsåterställning

När klienten återansluter till tjänsten med hjälp av tillförlitliga subprotokoler får klienten ett Connected meddelande som innehåller connectionId och reconnectionToken. Identifierar connectionId sessionen för anslutningen i tjänsten.

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

När WebSocket-anslutningen avbryts bör klienten försöka återansluta med samma connectionId för att återställa samma session. Klienter behöver inte förhandla med servern och hämta access_token. För att återställa anslutningen bör klienten i stället göra en WebSocket Connect-begäran direkt till tjänsten med tjänstens värdnamn, connection_id, och reconnection_token:

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

Anslut ion-återställningen kan misslyckas om nätverksproblemet inte har återställts ännu. Klienten bör fortsätta att försöka återansluta tills:

  1. Websocket-anslutningen är stängd med statuskoden 1008. Statuskoden innebär att connectionId har tagits bort från tjänsten.
  2. Ett återställningsfel fortsätter att inträffa i mer än 1 minut.

Publisher

Klienter som skickar händelser till händelsehanterare eller publicerar meddelanden till andra klienter kallas utgivare. Utgivare bör ange ackId i meddelandet att ta emot en bekräftelse från Web PubSub-tjänsten om att publiceringen av meddelandet lyckades eller inte.

ackId är identifieraren för meddelandet, varje nytt meddelande bör använda ett unikt ID. ackId Originalet ska användas vid återsändande av ett meddelande.

Ett exempelgruppsmeddelande:

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

Ett exempel på ack-svar:

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

När Web PubSub-tjänsten returnerar ett ack-svar med success: truehar meddelandet bearbetats av tjänsten och klienten kan förvänta sig att meddelandet levereras till alla prenumeranter.

När tjänsten får ett tillfälligt internt fel och meddelandet inte kan skickas till prenumeranten får utgivaren ett ack med success: false. Utgivaren bör läsa felet för att avgöra om meddelandet ska skickas igen eller inte. Om meddelandet skickas igen ska samma ackId sak användas.

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

Message Failure

Om tjänstens ack-svar går förlorat på grund av att WebSocket-anslutningen har släppts bör utgivaren skicka meddelandet igen med samma ackId efter återställningen. När meddelandet tidigare bearbetades av tjänsten skickas ett ack som innehåller ett Duplicate fel. Utgivaren bör sluta skicka det här meddelandet igen.

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

Message duplicated

Prenumerant

Klienter som tar emot meddelanden från händelsehanterare eller utgivare kallas prenumeranter. När anslutningarna avbryts på grund av nätverksproblem vet inte Web PubSub-tjänsten hur många meddelanden som skickades till prenumeranter. För att fastställa det senaste meddelandet som togs emot av prenumeranten skickar tjänsten ett datameddelande som innehåller en sequenceId. Prenumeranten svarar med ett sekvens-ack-meddelande:

En exempelsekvens ack:

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

sequenceId är ett inkrementellt uint64-tal i en anslutnings-ID-session. Prenumeranter bör registrera den största sequenceId som har tagits emot, acceptera endast meddelanden med större sequenceIdoch släppa meddelanden med en mindre eller lika sequenceIdmed . Prenumeranten bör ack med den största sequenceId som registrerats, så att tjänsten kan hoppa över att leverera meddelanden som prenumeranter redan har fått. Om prenumeranten till exempel svarar med ett sequenceAck med sequenceId: 5skickar tjänsten endast meddelanden med en sequenceId större än 5.

Alla meddelanden levereras till prenumeranter i ordning tills WebSocket-anslutningen avbryts. Med sequenceIdkan tjänsten veta hur många meddelanden som prenumeranter har tagit emot över WebSocket-anslutningar i en session. När en WebSocket-anslutning har avslutats kommer tjänsten att skicka meddelanden som inte bekräftas av prenumeranten. Tjänsten lagrar ett begränsat antal obemärkta meddelanden. När antalet meddelanden överskrider gränsen stänger tjänsten WebSocket-anslutningen och tar bort sessionen. Prenumeranter bör därför ack så sequenceId snart som möjligt.