Share via


Sottoprotocolo Protobuf WebSocket supportato da WebSocket di Azure

Questo documento descrive il sottoprotocolo protobuf.webpubsub.azure.v1.

Quando un client usa questo sottoprotocolo, è previsto che i frame di dati in uscita e in ingresso siano payload di buffer di protocollo (protobuf).

Panoramica

Subprotocol protobuf.webpubsub.azure.v1 consente al client di eseguire direttamente una sottoscrizione di pubblicazione (PubSub) anziché eseguire un round trip al server upstream. La connessione WebSocket con il protobuf.webpubsub.azure.v1 sottoprotocolo è denominata client WebSocket PubSocket.

In JavaScript, ad esempio, è possibile creare un client WebSocket PubSub con il sottoprotocolo protobuf usando:

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

Per un semplice client WebSocket, il server ha il ruolo necessario per la gestione degli eventi dai client. Una semplice connessione WebSocket attiva sempre un message evento quando invia messaggi e si basa sempre sul lato server per elaborare i messaggi ed eseguire altre operazioni. Con l'aiuto del protobuf.webpubsub.azure.v1 sottoprotocolo, un client autorizzato può partecipare a un gruppo usando richieste di join e pubblicare messaggi in un gruppo usando direttamente le richieste di pubblicazione. Il client può anche instradare i messaggi a vari gestori eventi upstream usando richieste di eventi per personalizzare l'evento a cui appartiene il messaggio.

Nota

Attualmente, il servizio Web PubSub supporta solo proto3.

Autorizzazioni

Un client WebSocket PubSocket può pubblicare solo in altri client quando è autorizzato. L'oggetto roles assegnato al client determina le autorizzazioni concesse al client:

Ruolo Autorizzazione
Non specificato Il client può inviare richieste di eventi.
webpubsub.joinLeaveGroup Il client può partecipare/lasciare qualsiasi gruppo.
webpubsub.sendToGroup Il client può pubblicare messaggi in qualsiasi gruppo.
webpubsub.joinLeaveGroup.<group> Il client può partecipare/lasciare il gruppo <group>.
webpubsub.sendToGroup.<group> Il client può pubblicare messaggi nel gruppo <group>.

Il server può concedere o revocare in modo dinamico le autorizzazioni client tramite API REST o SDK del server.

Richieste

Tutti i messaggi di richiesta rispettano il seguente formato protobuf:

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;
    }

    message SendToGroupMessage {
        string group = 1;
        optional uint64 ack_id = 2;
        MessageData data = 3;
    }

    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 MessageData {
    oneof data {
        string text_data = 1;
        bytes binary_data = 2;
        google.protobuf.Any protobuf_data = 3;
    }
}

Partecipare ai gruppi

Formato:

Impostare join_group_message.group sul nome del gruppo.

  • ackId è l'identità di ogni richiesta e deve essere univoca. Il servizio invia un messaggio di risposta ack per notificare il risultato del processo della richiesta. Altri dettagli sono disponibili in AckId e Ack Response

Lasciare i gruppi

Formato:

Impostare leave_group_message.group sul nome del gruppo.

  • ackId è l'identità di ogni richiesta e deve essere univoca. Il servizio invia un messaggio di risposta ack per notificare il risultato del processo della richiesta. Altri dettagli sono disponibili in AckId e Ack Response

Pubblicare messaggi

Formato:

  • ackId: identità univoca di ogni richiesta. Il servizio invia un messaggio di risposta ack per notificare il risultato del processo della richiesta. Altri dettagli sono disponibili in AckId e Ack Response

  • dataType: formato di dati, che può essere protobuf, texto binary a seconda di data in MessageData. I client riceventi possono usare dataType per elaborare correttamente il contenuto.

  • protobuf: quando si imposta send_to_group_message.data.protobuf_data, l'implicito dataType è protobuf. protobuf_datapuò essere di qualsiasi tipo di messaggio. Tutti gli altri client ricevono un file binario con codifica protobuf, che può essere deserializzato dall'SDK protobuf. I client che supportano solo il contenuto basato su testo ,ad esempio , json.webpubsub.azure.v1ricevono un file binario con codifica Base64.

  • text: quando si imposta send_to_group_message.data.text_data, l'implicito dataType è text. text_data deve essere una stringa. Tutti i client con altri protocolli ricevono una stringa con codifica UTF-8.

  • binary: quando si imposta send_to_group_message.data.binary_data, l'implicito dataType è binary. binary_data deve essere una matrice di byte. Tutti i client con altri protocolli ricevono un file binario non elaborato senza codifica protobuf. I client che supportano solo il contenuto basato su testo ,ad esempio , json.webpubsub.azure.v1ricevono un file binario con codifica Base64.

Caso 1: Pubblicare dati di testo

Impostare send_to_group_message.group su groupe impostare su send_to_group_message.data.text_data"text data".

  • Il client subprotocol protobuf in gruppo group riceve il frame binario e può usare DownstreamMessage per deserializzarlo.

  • I client del sottoprotocolo JSON in group ricevono:

    {
        "type": "message",
        "from": "group",
        "group": "group",
        "dataType" : "text",
        "data" : "text data"
    }
    
  • I semplici client WebSocket nella group stringa text datadi ricezione.

Caso 2: Pubblicare dati protobuf

Si supponga di avere un messaggio personalizzato:

message MyMessage {
    int32 value = 1;
}

Impostare su send_to_group_message.groupgroup e send_to_group_message.data.protobuf_data su Any.pack(MyMessage) con value = 1.

  • I client protobuf subprotocol in group ricevono il frame binario e possono usare DownstreamMessage per deserializzarlo.

  • Il client subprotocol in group riceve:

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

    Nota

    I dati sono un file binario protobuf con codifica Base64 deserializeable.

È possibile usare la definizione protobuf seguente e usarla Any.unpack() per deserializzarla:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}
  • I semplici client WebSocket in group ricevono il frame binario:

    # 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
    

Caso 3: Pubblicare dati binari

Impostare send_to_group_message.group su groupe impostare su send_to_group_message.data.binary_data[1, 2, 3].

  • Il client subprotocol protobuf in gruppo group riceve il frame binario e può usare DownstreamMessage per deserializzarlo.

  • Il client del sottoprotocolo JSON in gruppo group riceve:

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

    Poiché il client di sottoprotocolo JSON supporta solo la messaggistica basata su testo, il file binario è sempre con codifica Base64.

  • I semplici client WebSocket in group ricevono i dati binari nel frame binario:

    # Show in hexadecimal
    01 02 03
    

Inviare eventi personalizzati

È presente un oggetto implicito dataType, che può essere protobuf, texto binary, a seconda dell'oggetto dataType impostato. I client ricevitori possono usare dataType per gestire correttamente il contenuto.

  • protobuf: quando si imposta event_message.data.protobuf_data, l'implicito dataType è protobuf. Il protobuf_data valore può essere qualsiasi tipo protobuf supportato. Il gestore eventi riceve il file binario con codifica protobuf, che può essere deserializzato da qualsiasi SDK protobuf.

  • text: quando si imposta event_message.data.text_data, l'implicito dataType è text. Il text_data valore deve essere una stringa. Il gestore eventi riceve una stringa con codifica UTF-8.

  • binary: quando si imposta event_message.data.binary_data, l'implicito dataType è binary. Il binary_data valore deve essere una matrice di byte. Il gestore eventi riceve il frame binario non elaborato.

Caso 1: Inviare un evento con dati di testo

Impostare event_message.data.text_data su "text data".

Il gestore eventi upstream riceve una richiesta simile a:

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

Per Content-Type la richiesta HTTP CloudEvents è text/plain, dove=dataTypetext .

Caso 2: Inviare un evento con dati protobuf

Si supponga di aver ricevuto il seguente messaggio del cliente:

message MyMessage {
    int32 value = 1;
}

Impostare event_message.data.protobuf_data su any.pack(MyMessage) con value = 1

Il gestore eventi upstream riceve una richiesta simile a:

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

Per Content-Type la richiesta HTTP CloudEvents è application/x-protobuf, dove=dataTypeprotobuf .

I dati sono un file binario protobuf valido. È possibile usare quanto segue proto e any.unpack() per deserializzarlo:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}

Caso 3: Inviare un evento con dati binari

Impostare send_to_group_message.binary_data su [1, 2, 3].

Il gestore eventi upstream riceve una richiesta simile a:

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 

Per dataType=binary, per Content-Type la richiesta HTTP CloudEvents è application/octet-stream. Il frame WebSocket può essere in text formato per frame di messaggi di testo o file binari con codifica UTF-8 per binary i fotogrammi di messaggio.

Il servizio rifiuta il client se il messaggio non corrisponde al formato specificato.

Risposte

Tutti i messaggi di risposta rispettano il seguente formato protobuf:

message DownstreamMessage {
    oneof message {
        AckMessage ack_message = 1;
        DataMessage data_message = 2;
        SystemMessage system_message = 3;
    }
    
    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;
    }

    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;
        }
    }
}

I messaggi ricevuti dal client possono trovarsi in uno dei tre tipi seguenti: ack, messageo system.

Risposta Ack

Se la richiesta contiene ackId, il servizio restituisce una risposta ack per questa richiesta. L'implementazione client deve gestire questo meccanismo ack, tra cui:

  • In attesa della risposta ack per un'operazione asyncawait .
  • Verifica del timeout quando la risposta ack non viene ricevuta durante un determinato periodo.

L'implementazione del client deve sempre controllare prima di tutto se lo success stato è true o false. Quando lo success stato è false, il client può leggere dalla proprietà per i dettagli dell'errore error .

Risposta al messaggio

I client possono ricevere messaggi pubblicati da un gruppo aggiunto al client. Oppure possono ricevere messaggi dal ruolo di gestione del server quando il server invia messaggi a un client specifico o a un utente specifico.

Verrà sempre visualizzato un DownstreamMessage.DataMessage messaggio negli scenari seguenti:

  • Quando il messaggio proviene da un gruppo, from è group. Quando il messaggio proviene dal server, from è server.
  • Quando il messaggio proviene da un gruppo, group è il nome del gruppo.

Il mittente causerà l'invio dataType di uno dei messaggi seguenti:

  • Se dataType è text, usare message_response_message.data.text_data.
  • Se dataType è binary, usare message_response_message.data.binary_data.
  • Se dataType è protobuf, usare message_response_message.data.protobuf_data.
  • Se dataType è json, usare message_response_message.data.text_datae il contenuto è una stringa JSON serializzata.

Risposta di sistema

Il servizio Web PubSub può anche inviare risposte correlate al sistema al client.

Connesso

Quando il client si connette al servizio, viene visualizzato un DownstreamMessage.SystemMessage.ConnectedMessage messaggio.

Disconnesso

Quando il server chiude la connessione o il servizio rifiuta il client, viene visualizzato un DownstreamMessage.SystemMessage.DisconnectedMessage messaggio.

Passaggi successivi

Usare queste risorse per iniziare a creare un'applicazione personalizzata: