Azure Web PubSub Reliable JSON WebSocket-subprotocol

Het JSON WebSocket-subprotocol, json.reliable.webpubsub.azure.v1maakt de zeer betrouwbare uitwisseling van publiceren/abonneren rechtstreeks mogelijk tussen clients via de service zonder een retour naar de upstream-server.

In dit document wordt het subprotocol json.reliable.webpubsub.azure.v1beschreven.

Wanneer WebSocket-clientverbindingen worden verbroken vanwege onregelmatige netwerkproblemen, kunnen berichten verloren gaan. In een pub-/subsysteem worden uitgevers losgekoppeld van abonnees en kunnen ze de verbroken verbinding of het verlies van berichten van een abonnees niet detecteren.

Als u onregelmatige netwerkproblemen wilt oplossen en betrouwbare berichtbezorging wilt onderhouden, kunt u het Subprotocol Azure WebPubSub json.reliable.webpubsub.azure.v1 gebruiken om een Reliable PubSub WebSocket-client te maken.

Een Reliable PubSub WebSocket-client kan:

  • een verbinding herstellen na onregelmatige netwerkproblemen.
  • herstellen na verlies van berichten.
  • deelnemen aan een groep met behulp van deelnameaanvragen.
  • een groep verlaten met behulp van verlofaanvragen.
  • berichten rechtstreeks naar een groep publiceren met behulp van publicatieaanvragen.
  • Stream berichten rechtstreeks naar een groep via streamingverzoeken.
  • berichten rechtstreeks naar upstream gebeurtenis-handlers routeren met behulp van gebeurtenisaanvragen.

U kunt bijvoorbeeld een Reliable PubSub WebSocket-client maken met de volgende JavaScript-code:

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

Zie Hoe u betrouwbare clients kunt maken om opnieuw verbinding te maken en berichtbetrouwbaarheid te implementeren voor uitgevers- en abonneeclients.

Wanneer de client dit subprotocol gebruikt, moeten zowel uitgaande als binnenkomende gegevensframes JSON-nettoladingen bevatten.

Machtigingen

Een PubSub WebSocket-client kan alleen publiceren naar andere clients wanneer deze is geautoriseerd. De roles toegewezen aan de client bepaalt de machtigingen die aan de client zijn verleend:

Role Machtiging
Niet opgegeven De client kan gebeurtenisaanvragen verzenden.
webpubsub.joinLeaveGroup De client kan lid worden van elke groep of elke groep verlaten.
webpubsub.sendToGroup De client kan berichten publiceren naar elke groep.
webpubsub.joinLeaveGroup.<group> De client kan deelnemen aan/verlaten van de groep <group>.
webpubsub.sendToGroup.<group> De client kan berichten naar de groep <group>publiceren.
webpubsub.joinLeaveGroups.<pattern> De client kan lid worden/verlaten van een groep waarvan de naam overeenkomt <pattern> (zie rolpatronen van jokertekens).
webpubsub.sendToGroups.<pattern> De client kan berichten publiceren naar elke groep waarvan de naam overeenkomt <pattern> (zie rolpatronen voor jokertekens).

De server kan clientmachtigingen dynamisch verlenen of intrekken via REST API's of server-SDK's.

Opmerking

Jokertekenrollen (bijvoorbeeld webpubsub.sendToGroups.<pattern>) worden tijdens runtime nog niet ondersteund in REST API's of server-SDK's.

Verzoeken

Deelnemen aan groepen

Indeling:

{
    "type": "joinGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • ackId is de identiteit van elke aanvraag en moet uniek zijn. De service verzendt een ack-antwoordbericht om het procesresultaat van de aanvraag te melden. Zie AckId en Ack Response voor meer informatie

Groepen verlaten

Indeling:

{
    "type": "leaveGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • ackId is de identiteit van elke aanvraag en moet uniek zijn. De service verzendt een ack-antwoordbericht om het procesresultaat van de aanvraag te melden. Zie AckId en Ack Response voor meer informatie

Berichten publiceren

Indeling:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "ackId" : 1,
    "noEcho": true|false,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • ackId is de identiteit van elke aanvraag en moet uniek zijn. De service verzendt een ack-antwoordbericht om het procesresultaat van de aanvraag te melden. Zie AckId en Ack Response voor meer informatie
  • noEcho is optioneel. Als deze optie is ingesteld op true, wordt dit bericht niet teruggeklinkt naar dezelfde verbinding. Als deze niet is ingesteld, is de standaardwaarde onwaar.
  • dataType kan worden ingesteld op json, textof binary:
    • json: data kan elk type zijn dat JSON ondersteunt en wordt gepubliceerd zoals het is; Als dataType dit niet is opgegeven, wordt deze standaard ingesteld op json.
    • text: data moet de tekenreeksindeling hebben en de tekenreeksgegevens worden gepubliceerd;
    • binary: data moet de base64-indeling hebben en de binaire gegevens worden gepubliceerd;

Case 1: tekstgegevens publiceren:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "text",
    "data": "text data",
    "ackId": 1
}
  • De subprotocolclients die worden <group_name> ontvangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "text",
    "data" : "text data"
}
  • De eenvoudige WebSocket-clients ontvangen <group_name> de tekenreeks text data.

Case 2: JSON-gegevens publiceren:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    }
}
  • De subprotocolclients die worden <group_name> ontvangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "json",
    "data" : {
        "hello": "world"
    }
}
  • De eenvoudige WebSocket-clients ontvangen <group_name> de geserialiseerde tekenreeks {"hello": "world"}.

Case 3: binaire gegevens publiceren:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "binary",
    "data": "<base64_binary>",
    "ackId": 1
}
  • De subprotocolclients die worden <group_name> ontvangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "binary",
    "data" : "<base64_binary>", 
}
  • De eenvoudige WebSocket-clients ontvangen <group_name> de binaire gegevens in het binaire frame.

Begin met het streamen van berichten

Om een groepsstroom te starten, stuur je een sendToGroup verzoek met de stream eigenschap. Een stream start-verzoek bevat dataniet , dataType, of ackId.

Indeling:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "noEcho": true|false,
    "stream": {
        "streamId": "<stream_id>",
        "idleTimeoutMs": 300000
    }
}
  • stream.streamId is de identificatie van de logische stroom. Het moet een niet-lege string zijn en uniek zijn tussen actieve streams op dezelfde clientverbinding. Clientbibliotheken worden aanbevolen om een wereldwijd unieke waarde te genereren, zoals een GUID of UUID.
  • stream.idleTimeoutMs is optioneel. Als gespecificeerd, moet deze groter zijn dan 0. Als deze wordt weggelaten, is de standaard dienst milliseconden 300000 . De waarde is een inactieve time-out, niet de totale levensduur van de stream. Stuur stroomgegevens, stuur een stream keepalive, of beëindig de stream voordat deze time-out verstrijkt wanneer de applicatie de stream open moet houden.
  • noEcho is optioneel. Als het op true staat, worden streamberichten niet teruggestuurd naar dezelfde verbinding. Als deze niet is ingesteld, is de standaardwaarde onwaar.

Wanneer de stream wordt geaccepteerd, ontvangt de client een stream ack-respons met expectedSequenceId gezet op 1.

Stuur stroomdata

Om stroomgegevens te verzenden, stuur je een streamData verzoek met streamId, streamSequenceId, dataType, en data.

Indeling:

{
    "type": "streamData",
    "streamId": "<stream_id>",
    "streamSequenceId": 1,
    "dataType" : "json|text|binary",
    "data": {}
}
  • streamId Identificeert een actieve stream op dezelfde clientverbinding.
  • streamSequenceId is een positief UINT64-getal. Het eerste datafragment in een stroom gebruikt 1, en elk volgend datafragment voor hetzelfde streamId neemt precies 1toe met .
  • dataType kan worden ingesteld op json, text, of binary, met dezelfde datacoderingsregels als publiceerberichten.

Om een stream actief te houden zonder data aan abonnees te leveren, stuur je een streamData verzoek met alleen type en streamId.

{
    "type": "streamData",
    "streamId": "<stream_id>"
}

Einde van streamingberichten

Om een stream te beëindigen, stuur je een streamEnd verzoek.

Indeling:

{
    "type": "streamEnd",
    "streamId": "<stream_id>"
}

Om een stream te beëindigen met een door de applicatie gedefinieerde fout, voeg je de optionele error eigenschap op.

{
    "type": "streamEnd",
    "streamId": "<stream_id>",
    "error": {
        "message": "<error_detail>",
        "userErrorCode": "<application_error_code>"
    }
}
  • error.message is een optionele, door mensen leesbare foutmelding.
  • error.userErrorCode is een optionele, door de applicatie gedefinieerde foutcode.

Wanneer de stream wordt gesloten, ontvangt de uitgever een stream gesloten-antwoord.

Aangepaste gebeurtenissen verzenden

Indeling:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • ackId is de identiteit van elke aanvraag en moet uniek zijn. De service verzendt een ack-antwoordbericht om het procesresultaat van de aanvraag te melden. Zie AckId en Ack Response voor meer informatie

dataType kan een van text, binaryof json:

  • json: gegevens kunnen elk type json worden ondersteund en worden als zodanig gepubliceerd; De standaardwaarde is json.
  • text: gegevens hebben de tekenreeksindeling en de tekenreeksgegevens worden gepubliceerd;
  • binary: gegevens hebben de base64-indeling en de binaire gegevens worden gepubliceerd;

Case 1: gebeurtenis met tekstgegevens verzenden:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "text",
    "data": "text data", 
}

De upstream-gebeurtenishandler ontvangt gegevens die vergelijkbaar zijn met:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: text/plain
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

text data

De Content-Type HTTP-aanvraag voor CloudEvents is text/plain wanneerdataType.text

Case 2: gebeurtenis verzenden met JSON-gegevens:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json",
    "data": {
        "hello": "world"
    }, 
}

De upstream-gebeurtenishandler ontvangt gegevens die vergelijkbaar zijn met:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

{
    "hello": "world"
}

De Content-Type HTTP-aanvraag voor CloudEvents is application/json wanneer dataTypejson

Case 3: gebeurtenis verzenden met binaire gegevens:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "binary",
    "data": "base64_binary", 
}

De upstream-gebeurtenishandler ontvangt gegevens die vergelijkbaar zijn met:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

binary

De Content-Type HTTP-aanvraag voor CloudEvents is application/octet-stream wanneerdataType.binary Het WebSocket-frame kan worden text opgemaakt voor tekstberichtframes of UTF8 gecodeerde binaire bestanden voor binary berichtframes.

De Web PubSub-service weigert de client als het bericht niet overeenkomt met de beschreven indeling.

Ping

Indeling:

{
    "type": "ping",
}

De client kan een ping bericht naar de service verzenden om de Web PubSub-service in staat te stellen de liveness van de client te detecteren.

Reeks Ack

Indeling:

{
    "type": "sequenceAck",
    "sequenceId": "<sequenceId>",
}

Reliable PubSub WebSocket-client moet een reeks ack-bericht verzenden zodra het een bericht van de service ontvangt. Zie Hoe u betrouwbare clients kunt maken voor meer informatie

  • sequenceId is een incrementeel uint64-nummer van het ontvangen bericht.

Antwoorden

Berichten die door de cliënt worden ontvangen, kunnen verschillende typen zijn: ack, , , system, streamAckpong, , streamNack, en streamClosedmessage. Berichten met het type message hebben sequenceId een eigenschap. De client moet een reeks Ack naar de service verzenden zodra deze een bericht ontvangt.

Ack-antwoord

Wanneer de aanvraag bevat ackId, retourneert de service een ack-antwoord voor deze aanvraag. De client-implementatie moet dit ack-mechanisme verwerken, inclusief wachten op het ack-antwoord met behulp van een asyncawait bewerking en een time-outhandler hebben wanneer het ack-antwoord gedurende een bepaalde periode niet wordt ontvangen.

Indeling:

{
    "type": "ack",
    "ackId": 1, // The ack id for the request to ack
    "success": false, // true or false
    "error": {
        "name": "Forbidden|InternalServerError|Duplicate",
        "message": "<error_detail>"
    }
}

De client-implementatie MOET altijd controleren of dit success het geval is true of false eerst. Alleen wanneer success wordt false gelezen door errorde client.

Berichtantwoord

Clients kunnen berichten ontvangen die zijn gepubliceerd vanuit een groep die de client heeft toegevoegd of van de server, die werkt in een serverbeheerfunctie, berichten verzendt naar specifieke clients of gebruikers.

  1. Het antwoordbericht van een groep:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "group",
        "group": "<group_name>",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
        "fromUserId": "abc"
    }
    
  2. Het antwoordbericht van de server:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
    }
    

Case 1: Gegevens Hallo wereld verzenden naar de verbinding via REST API met Content-Type=text/plain

  • Een eenvoudige WebSocket-client ontvangt een webSocket-tekstframe met gegevens: Hallo wereld

  • Een PubSub WebSocket-client ontvangt het bericht in JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "text",
        "data": "Hello World", 
    }
    

Case 2: Gegevens { "Hello" : "World"} verzenden naar de verbinding via REST API met Content-Type=application/json

  • Een eenvoudige WebSocket-client ontvangt een websocket-frame met tekenreeksgegevens: { "Hello" : "World"};

  • Een PubSub WebSocket-client ontvangt het bericht in JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "json",
        "data": {
            "Hello": "World"
        }
    }
    

Als de REST API een tekenreeks Hallo wereld verzendt met behulp van application/json het inhoudstype, ontvangt de eenvoudige WebSocket-client de JSON-tekenreeks "Hallo wereld" die is verpakt in ".

Case 3: Binaire gegevens verzenden naar de verbinding via REST API met Content-Type=application/octet-stream

  • Een eenvoudige WebSocket-client ontvangt een binair WebSocket-frame met de binaire gegevens.

  • Een PubSub WebSocket-client ontvangt het bericht in JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "binary",
        "data": "<base64_binary>"
    }
    

Reactie op streamingberichten

Wanneer een bericht tot een stroom behoort, bevat het groepsbericht een stream eigenschap. De betrouwbare sequenceId blijft verbindingsscoped en is anders dan stream.streamSequenceId.

{
    "sequenceId": 1,
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType": "json|text|binary",
    "data": {},
    "fromUserId": "abc",
    "stream": {
        "streamId": "<stream_id>",
        "streamSequenceId": 1,
        "endOfStream": true,
        "error": {
            "name": "IdleTimeout|InternalServerError|Forbidden|Cancelled|UserError",
            "message": "<error_detail>",
            "userErrorCode": "<application_error_code>"
        }
    }
}
  • stream.streamId is de logische stroomidentificatie.
  • stream.streamSequenceId is het volgnummer van het bericht in de stroom.
  • stream.endOfStream is optioneel. Wanneer ingesteld op true, is het bericht het terminale bericht van de stroom.
  • stream.error is optioneel en is alleen aanwezig wanneer de stream eindigt met een foutmelding. userErrorCode is alleen aanwezig voor UserError.

Stream ack-respons

De dienst stuurt een streamAck antwoord om de geaccepteerde stroomgegevens te bevestigen en om de volgende verwachte stream sequence ID te rapporteren.

Indeling:

{
    "type": "streamAck",
    "streamId": "<stream_id>",
    "expectedSequenceId": 2
}

Stream nack-respons

De dienst stuurt een streamNack antwoord op een herhaalbare streamfout.

Indeling:

{
    "type": "streamNack",
    "streamId": "<stream_id>",
    "expectedSequenceId": 2,
    "name": "InvalidSequenceId|TransientError",
    "message": "<error_detail>"
}

Stream gesloten respons

De dienst stuurt een streamClosed antwoord wanneer de stream aan de uitgeverzijde wordt gesloten.

Indeling:

{
    "type": "streamClosed",
    "streamId": "<stream_id>",
    "error": {
        "name": "StreamNotFound|Forbidden|BadRequest|InternalServerError|IdleTimeout",
        "message": "<error_detail>"
    }
}

De error eigendom wordt weggelaten wanneer de stroom normaal wordt gesloten.

Systeemantwoord

De Web PubSub-service kan systeemgerelateerde antwoorden retourneren aan de client.

Pong-antwoord

De Web PubSub-service verzendt een pong bericht naar de client wanneer er een ping bericht van de client wordt ontvangen.

Indeling:

{
    "type": "pong",
}

Connected

Het antwoord op de clientverbindingsaanvraag:

{
    "type": "system",
    "event": "connected",
    "userId": "user1",
    "connectionId": "abcdefghijklmnop",
    "reconnectionToken": "<token>"
}

connectionId en reconnectionToken worden gebruikt voor opnieuw verbinden. Maak een verbindingsaanvraag met URI voor opnieuw verbinding maken:

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

Meer informatie vinden in Verbindingsherstel

Ontkoppeld

Het antwoord wanneer de server de verbinding sluit of wanneer de service de clientverbinding weigert:

{
    "type": "system",
    "event": "disconnected",
    "message": "reason"
}

Volgende stappen

Gebruik deze resources om te beginnen met het bouwen van uw eigen toepassing: