Subprotokol WebSocket protobuf yang didukung Azure Web PubSub

Dokumen ini menjelaskan subprotokol protobuf.webpubsub.azure.v1.

Ketika klien menggunakan subprotokol ini, baik frame data keluar dan masuk diharapkan menjadi payload buffer protokol (protobuf).

Gambaran Umum

Subprotokol protobuf.webpubsub.azure.v1 ​​memberdayakan klien untuk melakukan penerbitan/berlangganan (PubSub) secara langsung alih-alih bolak-balik ke server upstream. Sambungan WebSocket dengan subprotokol protobuf.webpubsub.azure.v1 disebut klien WebSocket PubSub.

Misalnya, di JavaScript, Anda dapat membuat klien WebSocket PubSub dengan subprotokol protobuf dengan menggunakan:

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

Untuk klien WebSocket sederhana, server harus memiliki peran untuk menangani peristiwa dari klien. Koneksi WebSocket sederhana selalu memicu acara message saat koneksi mengirim pesan, dan selalu mengandalkan kemampuan server untuk memproses pesan dan melakukan operasi lain. Dengan bantuan subprotokol protobuf.webpubsub.azure.v1, klien yang berwenang dapat bergabung dengan grup menggunakan permintaan bergabung dan menerbitkan pesan ke grup menggunakan permintaan penerbitan secara langsung. Klien juga dapat merutekan pesan ke penanganan aktivitas upstream yang berbeda dengan menggunakan permintaan pesan untuk menyesuaikan peristiwa tempat pesan tersebut berada.

Catatan

Saat ini, layanan Web PubSub hanya mendukung proto3.

Izin

Klien WebSocket PubSub hanya dapat menerbitkan ke klien lain saat diotorisasi. Yang roles ditetapkan ke klien menentukan izin yang diberikan kepada klien:

Peran Izin
Tidak ditentukan Klien dapat mengirim permintaan peristiwa.
webpubsub.joinLeaveGroup Klien dapat bergabung/meninggalkan grup mana pun.
webpubsub.sendToGroup Klien dapat menerbitkan pesan ke grup mana pun.
webpubsub.joinLeaveGroup.<group> Klien dapat bergabung/meninggalkan grup <group>.
webpubsub.sendToGroup.<group> Klien dapat menerbitkan pesan ke grup <group>.

Server dapat secara dinamis memberikan atau mencabut izin klien melalui REST API atau SDK server.

Permintaan

Semua pesan permintaan menggunakan format protobuf berikut:

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

Bergabung dengan grup

Format:

Atur join_group_message.group ke nama grup.

  • ackId adalah identitas dari setiap permintaan dan harus unik. Layanan mengirimkan pesan respons ack untuk memberi tahu hasil proses permintaan. Detail lebih lanjut dapat ditemukan di AckId dan Ack Response

Meninggalkan grup

Format:

Atur leave_group_message.group ke nama grup.

  • ackId adalah identitas dari setiap permintaan dan harus unik. Layanan mengirimkan pesan respons ack untuk memberi tahu hasil proses permintaan. Detail lebih lanjut dapat ditemukan di AckId dan Ack Response

Menerbitkan pesan

Format:

  • ackId: Identitas unik dari setiap permintaan. Layanan mengirimkan pesan respons ack untuk memberi tahu hasil proses permintaan. Detail lebih lanjut dapat ditemukan di AckId dan Ack Response

  • dataType: Format data, yang dapat berupa protobuf, text, atau binary tergantung pada data di MessageData. Klien penerima dapat menggunakan dataType untuk memproses konten dengan benar.

  • protobuf: Ketika Anda mengatur send_to_group_message.data.protobuf_data, implisitnya dataType adalah protobuf. protobuf_data Bisa dari jenis pesan apa pun. Semua klien lain menerima biner yang dienkodekan protobuf, yang dapat dideserialisasi oleh SDK protobuf. Klien yang hanya mendukung konten berbasis teks (misalnya, json.webpubsub.azure.v1) menerima biner yang dikodekan Base64.

  • text: Ketika Anda mengatur send_to_group_message.data.text_data, implisitnya dataType adalah text. text_data Harus berupa string. Semua klien dengan protokol lain menerima string yang dikodekan UTF-8.

  • binary: Ketika Anda mengatur send_to_group_message.data.binary_data, implisitnya dataType adalah binary. binary_data Harus berupa array byte. Semua klien dengan protokol lain menerima biner mentah tanpa pengkodean protobuf. Klien yang hanya mendukung konten berbasis teks (misalnya, json.webpubsub.azure.v1) menerima biner yang dikodekan Base64.

Kasus 1: Menerbitkan data teks

Atur send_to_group_message.group ke group, dan atur send_to_group_message.data.text_data ke "text data".

  • Klien subprotokol protobuf dalam grup group menerima bingkai biner dan dapat menggunakan DownstreamMessage untuk mendeserialisasi.

  • Klien subprotokul JSON dalam group menerima:

    {
        "type": "message",
        "from": "group",
        "group": "group",
        "dataType" : "text",
        "data" : "text data"
    }
    
  • Klien WebSocket sederhana dalam group string text datapenerimaan .

Kasus 2: Menerbitkan data protobuf

Mari kita asumsikan bahwa Anda memiliki pesan kustom:

message MyMessage {
    int32 value = 1;
}

Atur send_to_group_message.group ke group dan send_to_group_message.data.protobuf_data ke Any.pack(MyMessage) dengan value = 1.

  • Klien subprotokol protobuf dalam group menerima bingkai biner dan dapat menggunakan DownstreamMessage untuk mendeserialisasinya.

  • Klien subprotokl dalam group menerima:

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

    Catatan

    Data adalah biner protobuf yang dikodekan base64, yang dapat dideserialisasi.

Anda dapat menggunakan definisi protobuf berikut dan menggunakan Any.unpack() untuk mendeserialisasinya:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}
  • Klien WebSocket sederhana dalam group menerima bingkai biner:

    # 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
    

Kasus 3: Menerbitkan data biner

Atur send_to_group_message.group ke group, dan atur send_to_group_message.data.binary_data ke [1, 2, 3].

  • Klien subprotokol protobuf dalam grup group menerima bingkai biner dan dapat menggunakan DownstreamMessage untuk mendeserialisasi.

  • Klien subprotokol JSON dalam grup group menerima:

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

    Karena klien subprotocol JSON hanya mendukung pesan berbasis teks, biner selalu dikodekan Base64.

  • Klien WebSocket sederhana dalam group menerima data biner dalam bingkai biner:

    # Show in hexadecimal
    01 02 03
    

Kirim peristiwa kustom

Ada dataType implisit, yang bisa berupa protobuf, text, atau binary, bergantung pada dataType yang Anda tetapkan. Klien penerima dapat menggunakan dataType untuk menangani konten dengan benar.

  • protobuf: Ketika Anda mengatur event_message.data.protobuf_data, implisitnya dataType adalah protobuf. Nilainya protobuf_data dapat berupa jenis protobuf yang didukung. Penanganan aktivitas menerima biner yang dienkodekan protobuf, yang dapat dideserialisasi oleh SDK protobuf apapun.

  • text: Ketika Anda mengatur event_message.data.text_data, implisitnya dataType adalah text. Nilai text_data harus berupa string. Penanganan aktivitas menerima string yang dikodekan UTF-8.

  • binary: Ketika Anda mengatur event_message.data.binary_data, implisitnya dataType adalah binary. Nilai binary_data harus berupa array byte. Penanganan aktivitas menerima bingkai biner mentah.

Kasus 1: Mengirim peristiwa dengan data teks

Atur event_message.data.text_data ke "text data".

Penanganan aktivitas upstram menerima permintaan yang mirip dengan:

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 untuk permintaan HTTP CloudEvents adalah text/plain, di mana=dataTypetext .

Kasus 2: Mengirim peristiwa dengan data protobuf

Asumsikan bahwa Anda telah menerima pesan pelanggan berikut:

message MyMessage {
    int32 value = 1;
}

Atur event_message.data.protobuf_data ke any.pack(MyMessage) dengan value = 1

Penanganan aktivitas upstram menerima permintaan yang mirip dengan:

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 untuk permintaan HTTP CloudEvents adalah application/x-protobuf, di mana=dataTypeprotobuf .

Data adalah biner protobuf yang valid. Anda dapat menggunakan proto dan any.unpack() berikut untuk deserialisasi:

syntax = "proto3";

message MyMessage {
    int32 value = 1;
}

Kasus 3: Mengirim peristiwa dengan data biner

Atur send_to_group_message.binary_data ke [1, 2, 3].

Penanganan aktivitas upstram menerima permintaan yang mirip dengan:

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 

Untuk dataType=binary, Content-Type untuk permintaan HTTP CloudEvents adalah application/octet-stream. Bingkai WebSocket dapat berupa format text untuk bingkai pesan teks atau biner yang dikodekan UTF-8 untuk bingkai pesan binary.

Layanan menolak klien jika pesan tidak sesuai dengan format yang ditentukan.

Respons

Semua pesan respons menggunakan format protobuf berikut:

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

Pesan yang diterima oleh klien dapat berupa salah satu dari beberapa jenis: ack, message, atau system.

Respons ack

Jika permintaan berisi ackId, layanan akan mengembalikan respons ack untuk permintaan ini. Implementasi klien harus menangani mekanisme ack ini, termasuk:

  • Menunggu respons ack untuk asyncawait operasi.
  • Melakukan pemeriksaan timeout ketika respons ack tidak diterima selama periode tertentu.

Implementasi klien harus selalu memeriksa terlebih dahulu untuk melihat apakah status success adalah true atau false. Ketika status success adalah false, klien dapat membaca dari properti error untuk melihat rincian kesalahan.

Respons pesan

Klien dapat menerima pesan yang dipublikasikan dari grup di mana klien tergabung. Atau mereka dapat menerima pesan dari peran manajemen server ketika server mengirim pesan ke klien tertentu atau pengguna tertentu.

Anda akan selalu mendapatkan pesan DownstreamMessage.DataMessage dalam skenario berikut:

  • Ketika pesan berasal dari grup, from adalah group. Ketika pesan dari server, from adalah server.
  • Ketika pesan berasal dari grup, group adalah nama grup.

dataType pengirim akan menyebabkan salah satu pesan berikut dikirim:

  • Jika dataType adalah text, gunakanmessage_response_message.data.text_data.
  • Jika dataType adalah binary, gunakanmessage_response_message.data.binary_data.
  • Jika dataType adalah protobuf, gunakanmessage_response_message.data.protobuf_data.
  • Jika dataType adalah json, gunakanmessage_response_message.data.text_data, dan kontennya adalah string JSON berseri.

Respons sistem

Layanan Web PubSub juga dapat mengirim respons terkait sistem ke klien.

Tersambung

Ketika klien terhubung ke layanan, Anda akan menerima pesan DownstreamMessage.SystemMessage.ConnectedMessage.

Terputus

Ketika server menutup koneksi atau layanan menolak klien, Anda akan menerima pesan DownstreamMessage.SystemMessage.DisconnectedMessage.

Langkah berikutnya

Gunakan sumber daya ini untuk mulai membangun aplikasi Anda sendiri: