Betrouwbare WebSocket maken met subprotocol
Wanneer WebSocket-clientverbindingen worden verbroken vanwege onregelmatige netwerkproblemen, kunnen berichten verloren gaan. In een pub-/subsysteem worden uitgevers losgekoppeld van abonnees, zodat uitgevers mogelijk geen verbroken verbinding of verlies van berichten van abonnees detecteren. Het is van cruciaal belang voor clients om onregelmatige netwerkproblemen te overwinnen en betrouwbare berichtbezorging te onderhouden. Hiervoor kunt u een betrouwbare WebSocket-client maken met behulp van betrouwbare Azure Web PubSub-subprotocollen.
Reliable Protocol
De Web PubSub-service ondersteunt twee betrouwbare subprotocollen json.reliable.webpubsub.azure.v1
en protobuf.reliable.webpubsub.azure.v1
. Clients moeten de uitgevers-, abonnee- en herstelonderdelen van het subprotocol volgen om betrouwbaarheid te bereiken. Als het subprotocol niet goed kan worden geïmplementeerd, kan dit ertoe leiden dat de berichtbezorging niet werkt zoals verwacht of dat de service de client beëindigt vanwege protocolschendingen.
De eenvoudige manier: client-SDK gebruiken
De eenvoudigste manier om een betrouwbare client te maken, is door client-SDK te gebruiken. Client-SDK implementeert web pubsub-clientspecificatie en gebruikt json.reliable.webpubsub.azure.v1
standaard. Raadpleeg Publiceren/abonneren tussen clients voor snel starten.
De harde manier - met de hand implementeren
In de volgende zelfstudie wordt u begeleid bij het belangrijke onderdeel van het implementeren van de Web PubSub-clientspecificatie. Deze handleiding is niet bedoeld voor mensen die snel aan de slag willen, maar die het principe van het bereiken van betrouwbaarheid willen weten. Gebruik de client-SDK voor snel starten.
Initialisatie
Als u betrouwbare subprotocollen wilt gebruiken, moet u het subprotocol instellen bij het maken van WebSocket-verbindingen. In JavaScript kunt u de volgende code gebruiken:
Gebruik een betrouwbaar Json-subprotocol:
var pubsub = new WebSocket( "wss://test.webpubsub.azure.com/client/hubs/hub1", "json.reliable.webpubsub.azure.v1" );
Gebruik Protobuf reliable subprotocol:
var pubsub = new WebSocket( "wss://test.webpubsub.azure.com/client/hubs/hub1", "protobuf.reliable.webpubsub.azure.v1" );
Herstel van verbinding
Verbindingsherstel is de basis van het bereiken van betrouwbaarheid en moet worden geïmplementeerd bij het gebruik van de json.reliable.webpubsub.azure.v1
en protobuf.reliable.webpubsub.azure.v1
protocollen.
WebSocket-verbindingen zijn afhankelijk van TCP. Wanneer de verbinding niet wordt verbroken, zijn berichten verliesloos en bezorgd in volgorde. Om te voorkomen dat berichten verloren gaan via verbroken verbindingen, behoudt de Web PubSub-service de statusgegevens van de verbinding, inclusief groeps- en berichtgegevens. Deze informatie wordt gebruikt om de client te herstellen bij herstel van de verbinding
Wanneer de client opnieuw verbinding maakt met de service met behulp van betrouwbare subprotocollen, ontvangt de client een Connected
bericht met de connectionId
en reconnectionToken
. Hiermee connectionId
wordt de sessie van de verbinding in de service geïdentificeerd.
{
"type": "system",
"event": "connected",
"connectionId": "<connection_id>",
"reconnectionToken": "<reconnection_token>"
}
Zodra de WebSocket-verbinding is gestopt, moet de client proberen opnieuw verbinding te maken met hetzelfde connectionId
om dezelfde sessie te herstellen. Clients hoeven niet met de server te onderhandelen en de access_token
. Om de verbinding te herstellen, moet de client een WebSocket-verbindingsaanvraag rechtstreeks naar de service maken met de servicehostnaam, connection_id
en reconnection_token
:
wss://<service-endpoint>/client/hubs/<hub>?awps_connection_id=<connection_id>&awps_reconnection_token=<reconnection_token>
Herstel van de verbinding kan mislukken als het netwerkprobleem nog niet is hersteld. De client moet opnieuw proberen opnieuw verbinding te maken totdat:
- De WebSocket-verbinding wordt gesloten met statuscode 1008. De statuscode betekent dat de connectionId is verwijderd uit de service.
- Er blijft een herstelfout optreden gedurende meer dan 1 minuut.
Publisher
Clients die gebeurtenissen verzenden naar gebeurtenis-handlers of berichten publiceren naar andere clients, worden uitgevers genoemd. Uitgevers moeten in het bericht worden ingesteld ackId
om een bevestiging te ontvangen van de Web PubSub-service die het bericht heeft gepubliceerd of niet.
De ackId
id van het bericht is, elk nieuw bericht moet een unieke id gebruiken. Het origineel ackId
moet worden gebruikt bij het opnieuw verzenden van een bericht.
Een voorbeeldgroep verzendt een bericht:
{
"type": "sendToGroup",
"group": "group1",
"dataType": "text",
"data": "text data",
"ackId": 1
}
Een voorbeeld van een ack-antwoord:
{
"type": "ack",
"ackId": 1,
"success": true
}
Wanneer de Web PubSub-service een ack-antwoord retourneert, success: true
is het bericht verwerkt door de service en kan de client verwachten dat het bericht aan alle abonnees wordt bezorgd.
Wanneer de service een tijdelijke interne fout ondervindt en het bericht niet kan worden verzonden naar abonnee, ontvangt de uitgever een ack met success: false
. De uitgever moet de fout lezen om te bepalen of het bericht al dan niet opnieuw moet worden verzonden. Als het bericht opnieuw wordt verzonden, moet hetzelfde ackId
worden gebruikt.
{
"type": "ack",
"ackId": 1,
"success": false,
"error": {
"name": "InternalServerError",
"message": "Internal server error"
}
}
Als het ack-antwoord van de service verloren gaat omdat de WebSocket-verbinding is verbroken, moet de uitgever het bericht opnieuw verzenden met hetzelfde ackId
na herstel. Wanneer het bericht eerder door de service is verwerkt, wordt er een ack met een Duplicate
fout verzonden. De uitgever moet stoppen met het opnieuw verzenden van dit bericht.
{
"type": "ack",
"ackId": 1,
"success": false,
"error": {
"name": "Duplicate",
"message": "Message with ack-id: 1 has been processed"
}
}
Abonnee
Clients die berichten ontvangen van gebeurtenis-handlers of uitgevers, worden abonnees genoemd. Wanneer verbindingen worden afgebroken vanwege netwerkproblemen, weet de Web PubSub-service niet hoeveel berichten er naar abonnees zijn verzonden. Om te bepalen welk laatste bericht de abonnee heeft ontvangen, verzendt de service een gegevensbericht met een sequenceId
. De abonnee reageert met een reeks-ack-bericht:
Een voorbeeldreeks ack:
{
"type": "sequenceAck",
"sequenceId": 1
}
Het sequenceId
is een uint64 incrementeel getal in een sessie met de verbindings-id. Abonnees moeten het grootste sequenceId
opnemen dat het heeft ontvangen, alleen berichten accepteren met een grotere sequenceId
en berichten verwijderen met een kleiner of gelijk.sequenceId
De abonnee moet met het grootste sequenceId
aantal geregistreerde berichten worden overgeslagen, zodat de service opnieuw verzendende berichten kan overslaan die abonnees al hebben ontvangen. Als de abonnee bijvoorbeeld reageert met een sequenceAck
met sequenceId: 5
, wordt de service alleen berichten met een sequenceId
groter dan 5 opnieuw verzonden.
Alle berichten worden bezorgd bij abonnees totdat de WebSocket-verbinding wordt beëindigd. Hiermee sequenceId
kan de service weten hoeveel berichten abonnees hebben ontvangen via WebSocket-verbindingen in een sessie. Nadat een WebSocket-verbinding is afgevallen, worden berichten die niet door de abonnee zijn bevestigd, opnieuw verzonden. De service slaat een beperkt aantal niet-bekende berichten op. Wanneer het aantal berichten de limiet overschrijdt, wordt de WebSocket-verbinding gesloten en wordt de sessie verwijderd. Abonnees moeten dus zo sequenceId
snel mogelijk afhalen.