Underprotokol för Azure Web PubSub-stödd protobuf WebSocket

Det här dokumentet beskriver delprotokolen protobuf.webpubsub.azure.v1.

När en klient använder den här delprotokolen förväntas både utgående och inkommande dataramar vara protokollbuffertar (protobuf) nyttolaster.

Översikt

Subprotocol protobuf.webpubsub.azure.v1 ger klienten möjlighet att göra en publicera-prenumerera (PubSub) direkt i stället för att göra en tur och retur till den överordnade servern. WebSocket-anslutningen med subprotokolen protobuf.webpubsub.azure.v1 kallas för en PubSub WebSocket-klient.

I JavaScript kan du till exempel skapa en PubSub WebSocket-klient med protobuf-subprotokolen med hjälp av:

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

För en enkel WebSocket-klient har servern den roll som krävs för att hantera händelser från klienter. En enkel WebSocket-anslutning utlöser alltid en message händelse när den skickar meddelanden, och den förlitar sig alltid på serversidan för att bearbeta meddelanden och utföra andra åtgärder. Med hjälp av delprotokolen protobuf.webpubsub.azure.v1 kan en auktoriserad klient ansluta till en grupp med hjälp av anslutningsbegäranden och publicera meddelanden till en grupp genom att använda publicera begäranden direkt. Klienten kan också dirigera meddelanden till olika överordnade händelsehanterare genom att använda händelsebegäranden för att anpassa händelsen som meddelandet tillhör.

Kommentar

Web PubSub-tjänsten stöder för närvarande endast proto3.

Behörigheter

En PubSub WebSocket-klient kan bara publicera till andra klienter när den är auktoriserad. Den roles tilldelade klienten avgör vilka behörigheter som beviljats klienten:

Roll Behörighet
Har inte angetts Klienten kan skicka händelsebegäranden.
webpubsub.joinLeaveGroup Klienten kan ansluta/lämna valfri grupp.
webpubsub.sendToGroup Klienten kan publicera meddelanden till valfri grupp.
webpubsub.joinLeaveGroup.<group> Klienten kan ansluta/lämna gruppen <group>.
webpubsub.sendToGroup.<group> Klienten kan publicera meddelanden till gruppen <group>.
webpubsub.joinLeaveGroups.<pattern> Klienten kan ansluta/lämna valfri grupp vars namn matchar <pattern> (se Mönster för jokerteckengrupproll).
webpubsub.sendToGroups.<pattern> Klienten kan publicera meddelanden till alla grupper vars namn matchar <pattern> (se Mönster för jokerteckengrupproll).

Servern kan dynamiskt bevilja eller återkalla klientbehörigheter via REST-API:er eller server-SDK:er.

Kommentar

Jokerteckenroller (t.ex. webpubsub.sendToGroups.<pattern>) stöds inte i REST-API:er eller server-SDK:er under körning ännu.

begäranden

Alla begärandemeddelanden följer följande protobuf-format:

syntax = "proto3";

import "google/protobuf/any.proto";

message UpstreamMessage {
    oneof message {
        SendToGroupMessage send_to_group_message = 1;
        EventMessage event_message = 5;
        JoinGroupMessage join_group_message = 6;
        LeaveGroupMessage leave_group_message = 7;
        SequenceAckMessage sequence_ack_message = 8;
        PingMessage ping_message = 9;
        StreamDataMessage stream_data_message = 13;
        StreamEndMessage stream_end_message = 14;
    }

    message SendToGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
        MessageData data = 3;
        optional bool no_echo = 4;
        StreamStartInfo stream = 7;
    }

    message StreamStartInfo {
        string stream_id = 1;
        optional uint32 idle_timeout_ms = 2;
    }

    message EventMessage {
        string event = 1;
        MessageData data = 2;
        optional uint64 ack_id = 3;
    }
    
    message JoinGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
    }

    message LeaveGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
    }

    message SequenceAckMessage {
        uint64 sequence_id = 1;
    }

    message PingMessage {
    }

    message StreamDataMessage {
        string stream_id = 1;
        optional uint64 stream_sequence_id = 2;
        MessageData data = 3;
    }

    message StreamEndMessage {
        string stream_id = 1;
        optional StreamEndError error = 2;

        message StreamEndError {
            optional string message = 1;
            optional string user_error_code = 2;
        }
    }
}

message MessageData {
    oneof data {
        string text_data = 1;
        bytes binary_data = 2;
        google.protobuf.Any protobuf_data = 3;
    }
}

Koppla grupper

Format:

Ange join_group_message.group gruppnamnet.

Lämna grupper

Format:

Ange leave_group_message.group gruppnamnet.

Publicera meddelanden

Format:

  • ackId: Den unika identiteten för varje begäran. Tjänsten skickar ett ack-svarsmeddelande för att meddela processresultatet för begäran. Mer information finns på AckId och Ack Response

  • dataType: Dataformatet, som kan vara protobuf, texteller binary beroende på data i MessageData. De mottagande klienterna kan använda dataType för att bearbeta innehållet korrekt.

  • protobuf: När du anger send_to_group_message.data.protobuf_dataär dataTypeimplicit protobuf . protobuf_data kan vara av typen Valfritt meddelande. Alla andra klienter får en protobuf-kodad binär fil, som kan deserialiseras av protobuf SDK. Klienter som endast stöder textbaserat innehåll (till exempel json.webpubsub.azure.v1) får en Base64-kodad binär fil.

  • text: När du anger send_to_group_message.data.text_dataär dataTypeimplicit text . text_data bör vara en sträng. Alla klienter med andra protokoll får en UTF-8-kodad sträng.

  • binary: När du anger send_to_group_message.data.binary_dataär dataTypeimplicit binary . binary_data bör vara en bytematris. Alla klienter med andra protokoll får en rå binär fil utan protobuf-kodning. Klienter som endast stöder textbaserat innehåll (till exempel json.webpubsub.azure.v1) får en Base64-kodad binär fil.

Fall 1: Publicera textdata

Ange send_to_group_message.group till groupoch inställt send_to_group_message.data.text_data"text data".

  • Protobuf-subprotokolklienten i gruppen group tar emot den binära ramen och kan använda DownstreamMessage för att deserialisera den.

  • JSON-underprotokolklienter i group tar emot:

    {
        "type": "message",
        "from": "group",
        "group": "group",
        "dataType" : "text",
        "data" : "text data"
    }
    
  • De enkla WebSocket-klienterna i group ta emot strängen text data.

Fall 2: Publicera protobuf-data

Anta att du har ett anpassat meddelande:

message MyMessage {
    int32 value = 1;
}

Ange send_to_group_message.group till group och send_to_group_message.data.protobuf_data till Any.pack(MyMessage) med value = 1.

  • Protobuf-subprotokolklienterna i group tar emot den binära ramen och kan använda DownstreamMessage för att deserialisera den.

  • Subprotokolklienten i group tar emot:

    {
        "type": "message",
        "from": "group",
        "group": "G",
        "dataType" : "protobuf",
        "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes
    }
    

    Kommentar

    Data är en Base64-kodad, deserializeable protobuf binär.

Du kan använda följande protobuf-definition och använda Any.unpack() för att deserialisera den:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}
  • De enkla WebSocket-klienterna i group tar emot den binära ramen:

    # Show in hexadecimal
    0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01
    

Fall 3: Publicera binära data

Ange send_to_group_message.group till groupoch inställt send_to_group_message.data.binary_data[1, 2, 3].

  • Protobuf-subprotokolklienten i gruppen group tar emot den binära ramen och kan använda DownstreamMessage för att deserialisera den.

  • JSON-underprotokolklienten i gruppen group tar emot:

    {
        "type": "message",
        "from": "group",
        "group": "group",
        "dataType" : "binary",
        "data" : "AQID", // Base64-encoded [1,2,3]
    }
    

    Eftersom JSON-subprotokolklienten endast stöder textbaserade meddelanden är binärfilen alltid Base64-kodad.

  • De enkla WebSocket-klienterna i group tar emot binära data i den binära ramen:

    # Show in hexadecimal
    01 02 03
    

Börja strömma meddelanden

För att starta en gruppström, ställ send_to_group_message.group in på målgruppen och ställ send_to_group_message.stream in på ett StreamStartInfo meddelande. En stream start-förfrågan sätter send_to_group_message.data inte eller send_to_group_message.ack_id.

  • send_to_group_message.stream.stream_id är identifieraren för den logiska strömmen. Det måste vara en icke-tom sträng och vara unik bland aktiva strömmar på samma klientanslutning. Klientbibliotek rekommenderas för att generera ett globalt unikt värde, såsom en GUID eller UUID.
  • send_to_group_message.stream.idle_timeout_ms är valfritt. Om specificerat måste den vara större än 0. Om den utelämnas är servicestandarden millisekunder 300000 . Värdet är en inaktiv timeout, inte en total strömlivslängd. Skicka strömdata, skicka en ström som hålls vid liv, eller avsluta strömmen innan denna timeout går ut när applikationen behöver hålla strömmen öppen.
  • send_to_group_message.no_echo är valfritt. Om det är sant inställt på true skickas inte streammeddelanden tillbaka till samma anslutning. Om det inte anges är standardvärdet falskt.

När strömmen accepteras får klienten ett ström-ack-svar med expected_sequence_id satt till 1.

Skicka strömmande data

För att skicka strömdata, sätt stream_data_message.stream_id, stream_data_message.stream_sequence_id, och stream_data_message.data.

  • stream_data_message.stream_id identifierar en aktiv ström på samma klientanslutning.
  • stream_data_message.stream_sequence_id är ett positivt UINT64-tal. Det första datafragmentet i en ström använder 1, och varje efterföljande datafragment för samma stream_id ökar med exakt 1.
  • stream_data_message.data använder samma MessageData kodningsregler som publicera meddelanden.

För att hålla en ström aktiv utan att leverera data till abonnenter, skicka stream_data_message med endast stream_id inställt.

Avsluta strömningsmeddelanden

För att avsluta en ström, sätt stream_end_message.stream_id.

För att avsluta en ström med ett applikationsdefinierat fel, sätt stream_end_message.error.

  • stream_end_message.error.message är ett valfritt mänskligt läsbart felmeddelande.
  • stream_end_message.error.user_error_code är en valfri felkod definierad av applikationen.

När strömmen stängs får utgivaren ett svar om strömmen stängd.

Skicka anpassade händelser

Det finns en implicit dataType, som kan vara protobuf, texteller binary, beroende på vilken dataType du har angett. Mottagarklienterna kan använda dataType för att hantera innehållet korrekt.

  • protobuf: När du anger event_message.data.protobuf_dataär dataTypeimplicit protobuf . Värdet protobuf_data kan vara valfri protobuf-typ som stöds. Händelsehanteraren tar emot den protobuf-kodade binärfilen, som kan deserialiseras av valfri protobuf-SDK.

  • text: När du anger event_message.data.text_dataär dataTypeimplicit text . Värdet text_data ska vara en sträng. Händelsehanteraren tar emot en UTF-8-kodad sträng.

  • binary: När du anger event_message.data.binary_dataär dataTypeimplicit binary . Värdet binary_data ska vara en bytematris. Händelsehanteraren tar emot den binära råramen.

Fall 1: Skicka en händelse med textdata

Ställ in event_message.data.text_data"text data".

Den överordnade händelsehanteraren tar emot en begäran som liknar:

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

Content-Type För CloudEvents HTTP-begäran är text/plain, där dataType=text.

Fall 2: Skicka en händelse med protobuf-data

Anta att du har fått följande kundmeddelande:

message MyMessage {
    int32 value = 1;
}

Ange event_message.data.protobuf_data till any.pack(MyMessage) med value = 1

Den överordnade händelsehanteraren tar emot en begäran som liknar:

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>

// Just show in hexadecimal; read it as binary
0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01

Content-Type För CloudEvents HTTP-begäran är application/x-protobuf, där dataType=protobuf.

Data är en giltig protobuf-binär fil. Du kan använda följande proto och any.unpack() deserialisera det:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}

Fall 3: Skicka en händelse med binära data

Ställ in send_to_group_message.binary_data[1, 2, 3].

Den överordnade händelsehanteraren tar emot en begäran som liknar:

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>

// Just show in hexadecimal; you need to read it as binary
01 02 03 

dataType För =binaryContent-Typeär application/octet-streamför CloudEvents HTTP-begäran . WebSocket-ramen kan vara i text format för textmeddelanderamar eller UTF-8-kodade binärfiler för binary meddelanderamar.

Tjänsten nekar klienten om meddelandet inte matchar det angivna formatet.

Ping

Klienten kan skicka en PingMessage till tjänsten för att aktivera Web PubSub-tjänsten för att identifiera klientens livskraft.

Svar

Alla svarsmeddelanden följer följande protobuf-format:

message DownstreamMessage {
    oneof message {
        AckMessage ack_message = 1;
        DataMessage data_message = 2;
        SystemMessage system_message = 3;
        PongMessage pong_message = 4;
        StreamAckMessage stream_ack_message = 6;
        StreamNackMessage stream_nack_message = 7;
        StreamClosedMessage stream_closed_message = 8;
    }
    
    message AckMessage {
        uint64 ack_id = 1;
        bool success = 2;
        optional ErrorMessage error = 3;
    
        message ErrorMessage {
            string name = 1;
            string message = 2;
        }
    }

    message DataMessage {
        string from = 1;
        optional string group = 2;
        MessageData data = 3;
        StreamInfo stream = 6;
    }

    message SystemMessage {
        oneof message {
            ConnectedMessage connected_message = 1;
            DisconnectedMessage disconnected_message = 2;
        }
    
        message ConnectedMessage {
            string connection_id = 1;
            string user_id = 2;
        }

        message DisconnectedMessage {
            string reason = 2;
        }
    }

    message PongMessage {
    }

    message StreamAckMessage {
        string stream_id = 1;
        uint64 expected_sequence_id = 2;
    }

    message StreamNackMessage {
        string stream_id = 1;
        string name = 2;
        string message = 3;
        uint64 expected_sequence_id = 4;
    }

    message StreamClosedMessage {
        string stream_id = 1;
        optional StreamClosedError error = 2;

        message StreamClosedError {
            string name = 1;
            string message = 2;
        }
    }
}

message StreamInfo {
    string stream_id = 1;
    uint64 stream_sequence_id = 2;
    optional bool end_of_stream = 3;
    optional StreamError error = 4;

    message StreamError {
        string name = 1;
        string message = 2;
        string user_error_code = 3;
    }
}

Meddelanden som tas emot av klienten kan vara ack, message, system, , pong, streamAck, streamNack, , eller streamClosed.

Ack-svar

Om begäran innehåller returnerar ackIdtjänsten ett ack-svar för den här begäran. Klientimplementeringen bör hantera den här ack-mekanismen, inklusive:

  • Väntar på ack-svaret för en asyncawait åtgärd.
  • Ha en timeout-kontroll när ack-svaret inte tas emot under en viss period.

Klientimplementeringen bör alltid kontrollera först om statusen success är true eller false. När statusen success är falsekan klienten läsa från egenskapen error för felinformation.

Meddelandesvar

Klienter kan ta emot meddelanden som publicerats från en grupp som klienten har anslutit. Eller så kan de ta emot meddelanden från serverhanteringsrollen när servern skickar meddelanden till en specifik klient eller en specifik användare.

Du får alltid ett DownstreamMessage.DataMessage meddelande i följande scenarier:

  • När meddelandet kommer från en grupp from är group. När meddelandet kommer från servern from är server.
  • När meddelandet kommer från en grupp group är gruppnamnet.

Avsändarens dataType gör att något av följande meddelanden skickas:

  • Om dataType är textanvänder du message_response_message.data.text_data.
  • Om dataType är binaryanvänder du message_response_message.data.binary_data.
  • Om dataType är protobufanvänder du message_response_message.data.protobuf_data.
  • Om dataType är jsonanvänder du message_response_message.data.text_dataoch innehållet är en serialiserad JSON-sträng.

När ett gruppmeddelande tillhör en ström, DownstreamMessage.DataMessage.stream sätts .

  • stream.stream_id är den logiska strömidentifieraren.
  • stream.stream_sequence_id är sekvensnumret för meddelandet i strömmen.
  • stream.end_of_stream är valfritt. När det sätts till trueär meddelandet strömmens terminalmeddelande.
  • stream.error är valfritt och finns endast när strömmen avslutas med ett fel. user_error_code är endast närvarande för UserError.

Stream ack-respons

Tjänsten skickar DownstreamMessage.StreamAckMessage för att bekräfta accepterad strömdata och för att rapportera nästa strömsekvens-ID den förväntar sig.

  • stream_id är den logiska strömidentifieraren.
  • expected_sequence_id är nästa strömsekvens-ID som tjänsten förväntar sig.

Stream nack-respons

Tjänsten skickar DownstreamMessage.StreamNackMessage efter ett återdrivet strömfel.

  • stream_id är den logiska strömidentifieraren.
  • expected_sequence_id är nästa strömsekvens-ID som tjänsten förväntar sig.
  • name kan vara InvalidSequenceId eller TransientError.
  • message innehåller feluppgifter.

Strömstängt respons

Tjänsten skickar DownstreamMessage.StreamClosedMessage när utgivarens stream stängs.

  • stream_id är den logiska strömidentifieraren.
  • error utelämnas när strömmen är normalt stängd.
  • error.namekan vara , , , , InternalServerError, eller IdleTimeout. BadRequestForbiddenStreamNotFound
  • error.message innehåller feluppgifter.

Systemsvar

Web PubSub-tjänsten kan också skicka systemrelaterade svar till klienten.

Connected

När klienten ansluter till tjänsten får du ett DownstreamMessage.SystemMessage.ConnectedMessage meddelande.

Frånkopplad

När servern stänger anslutningen eller om tjänsten nekar klienten får du ett DownstreamMessage.SystemMessage.DisconnectedMessage meddelande.

Pong-svar

Tjänsten Web PubSub skickar en PongMessage till klienten när den tar emot en PingMessage från klienten.

Nästa steg

Använd dessa resurser för att börja skapa ett eget program: