このドキュメントでは、サブプロトコル protobuf.webpubsub.azure.v1 について説明します。
クライアントがこのサブプロトコルを使用している場合、送信データ フレームと受信データ フレームの両方がプロトコル バッファー (protobuf) ペイロードである必要があります。
概要
サブプロトコル protobuf.webpubsub.azure.v1 を使用すると、クライアントでは、上流サーバーへのラウンド トリップではなく、直接の発行またはサブスクライブ (PubSub) を行うことができます。
protobuf.webpubsub.azure.v1 サブプロトコルを持つ WebSocket 接続を、PubSub WebSocket クライアントと呼びます。
たとえば、JavaScript では、次のコードを使用して、protobuf サブプロトコルを使用する PubSub WebSocket クライアントを作成できます。
// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');
シンプルな WebSocket クライアントの場合、サーバーにはクライアントからイベントを処理するために必要なロールがあります。 シンプルな WebSocket 接続では、メッセージを送信するときには必ず message イベントをトリガーします。また、常にサーバー側に依存して、メッセージを処理したり他の操作を行ったりします。
protobuf.webpubsub.azure.v1 サブプロトコルを使用することで、許可されているクライアントは、参加要求を使用してグループに参加し、発行要求を直接使用してグループにメッセージを発行できます。 クライアントは、イベント要求を使用して、メッセージが属するイベントをカスタマイズすることで、さまざまな上流イベント ハンドラにメッセージをルーティングすることもできます。
Note
現在、Web PubSub サービスは proto3 のみをサポートしています。
アクセス許可
PubSub WebSocket クライアントは、許可されている場合にのみ他のクライアントに発行できます。 クライアントに割り当てられた roles によって、そのクライアントに付与されるアクセス許可が決まります。
| 役割 | アクセス許可 |
|---|---|
| 指定なし | クライアントは、イベント要求を送信できます。 |
webpubsub.joinLeaveGroup |
クライアントは、どのグループについても、参加と脱退が可能です。 |
webpubsub.sendToGroup |
クライアントは、どのグループにもメッセージを発行できます。 |
webpubsub.joinLeaveGroup.<group> |
クライアントはグループ <group> について、参加と脱退が可能です。 |
webpubsub.sendToGroup.<group> |
クライアントはグループ <group> にメッセージを発行できます。 |
webpubsub.joinLeaveGroups.<pattern> |
クライアントは、名前が <pattern> と一致するすべてのグループに参加または脱退できます ( ワイルドカード グループの役割パターンを参照)。 |
webpubsub.sendToGroups.<pattern> |
クライアントは、名前が <pattern> と一致する任意のグループにメッセージを発行できます ( ワイルドカード グループの役割パターンを参照)。 |
REST API またはサーバー SDK を使用して、サーバーからクライアントのアクセス許可を動的に付与または取り消すことができます。
Note
ワイルドカード ロール ( webpubsub.sendToGroups.<pattern> など) は、実行時に REST API またはサーバー SDK ではまだサポートされていません。
要求
すべての要求メッセージは、次の 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;
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;
}
}
グループに参加する
形式:
join_group_message.group をグループ名に設定します。
-
ackIdは各要求の ID で、一意である必要があります。 要求の処理結果を通知するために、サービスから確認応答メッセージが送信されます。 詳細については、AckId と確認応答に関するページを参照してください。
グループを脱退する
形式:
leave_group_message.group をグループ名に設定します。
-
ackIdは各要求の ID で、一意である必要があります。 要求の処理結果を通知するために、サービスから確認応答メッセージが送信されます。 詳細については、AckId と確認応答に関するページを参照してください。
メッセージを発行する
形式:
ackId: 各要求の一意の ID。 要求の処理結果を通知するために、サービスから確認応答メッセージが送信されます。 詳細については、AckId と確認応答に関するページを参照してください。dataType:protobufのtextに応じて、binary、data、またはMessageDataであるデータ形式。 受信側のクライアントは、dataTypeを使用してコンテンツを正しく処理できます。protobuf:send_to_group_message.data.protobuf_dataを設定した場合、暗黙的なdataTypeはprotobufです。protobuf_dataは、任意のメッセージ型にすることができます。 他のすべてのクライアントは protobuf でエンコードされたバイナリを受け取り、protobuf SDK によって逆シリアル化できます。 テキスト ベースのコンテンツのみをサポートするクライアント (例:json.webpubsub.azure.v1) は、Base64 でエンコードされたバイナリを受け取ります。text:send_to_group_message.data.text_dataを設定した場合、暗黙的なdataTypeはtextです。text_dataは文字列である必要があります。 他のプロトコルを使用するすべてのクライアントは、UTF-8 でエンコードされた文字列を受け取ります。binary:send_to_group_message.data.binary_dataを設定した場合、暗黙的なdataTypeはbinaryです。binary_dataはバイト配列である必要があります。 他のプロトコルを使用するすべてのクライアントは、protobuf エンコードされていない未加工のバイナリを受け取ります。 テキスト ベースのコンテンツのみをサポートするクライアント (例:json.webpubsub.azure.v1) は、Base64 でエンコードされたバイナリを受け取ります。
ケース 1: テキスト データを発行する
send_to_group_message.group を group に設定し、send_to_group_message.data.text_data を "text data" に設定します。
グループ
group内の protobuf サブプロトコル クライアントはバイナリ フレームを受け取り、DownstreamMessage を使用して逆シリアル化できます。groupの JSON サブプロトコル クライアントは、以下を受け取ります。{ "type": "message", "from": "group", "group": "group", "dataType" : "text", "data" : "text data" }groupのシンプル WebSocket クライアントは、文字列text dataを受け取ります。
ケース 2: protobuf データを発行する
カスタム メッセージがある場合を想定します。
message MyMessage {
int32 value = 1;
}
send_to_group_message.group を group に、send_to_group_message.data.protobuf_data を Any.pack(MyMessage) に設定し、value = 1 を指定します。
group内の protobuf サブプロトコル クライアントはバイナリ フレームを受け取り、DownstreamMessage を使用して逆シリアル化できます。group内のサブプロトコル クライアントは以下を受け取ります。{ "type": "message", "from": "group", "group": "G", "dataType" : "protobuf", "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes }Note
データは、Base64 でエンコードされた逆シリアル化可能な protobuf バイナリです。
次の protobuf 定義を使用し、Any.unpack() を使用して逆シリアル化できます。
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
groupのシンプル WebSocket クライアントは、バイナリー データを受け取ります。# 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
ケース 3: バイナリ データを発行する
send_to_group_message.group を group に設定し、send_to_group_message.data.binary_data を [1, 2, 3] に設定します。
グループ
group内の protobuf サブプロトコル クライアントはバイナリ フレームを受け取り、DownstreamMessage を使用して逆シリアル化できます。グループ
group内の JSON サブプロトコル クライアントは以下を受け取ります。{ "type": "message", "from": "group", "group": "group", "dataType" : "binary", "data" : "AQID", // Base64-encoded [1,2,3] }JSON サブプロトコル クライアントはテキスト ベースのメッセージングのみをサポートします。バイナリは常に Base64 でエンコードされます。
groupのシンプル WebSocket クライアントは、次のバイナリ フレームのバイナリ データを受け取ります。# Show in hexadecimal 01 02 03
メッセージのストリーミングを始めましょう
グループストリームを開始するには、 send_to_group_message.group をターゲットグループに設定し、 send_to_group_message.stream を StreamStartInfo メッセージに設定します。 ストリームスタートリクエストは send_to_group_message.data や send_to_group_message.ack_idを設定しません。
-
send_to_group_message.stream.stream_idは論理ストリームの識別子です。 文字列は空でなければならず、同じクライアント接続上のアクティブなストリーム間で一意でなければなりません。 クライアントライブラリは、GUIDやUUIDなどのグローバルな一意値を生成することが推奨されています。 -
send_to_group_message.stream.idle_timeout_msはオプションです。 もし指定されている場合は、0より大きくなければなりません。 省略すると、サービスのデフォルトは300000ミリ秒となります。 値としてはアイドルタイムアウトであって、ストリームの総寿命ではありません。 ストリームデータを送信するか、ストリームキーパライブを送信するか、このタイムアウトが経過する前にストリームを終了するか、アプリケーションがストリームを開いたままにしておく必要があります。 -
send_to_group_message.no_echoはオプションです。 trueに設定すると、ストリームメッセージは同じ接続にエコーバックされません。 設定しない場合の既定値は false です。
ストリームが受け入れられると、クライアントはexpected_sequence_idが1に設定されたストリームack応答を受け取ります。
ストリーミングデータを送信する
ストリームデータを送るには、 stream_data_message.stream_id、 stream_data_message.stream_sequence_id、 stream_data_message.dataを設定します。
-
stream_data_message.stream_id同じクライアント接続上のアクティブなストリームを識別します。 -
stream_data_message.stream_sequence_idは正のuint64数です。 ストリームの最初のデータ断片は1を使用し、同じstream_idの後続のデータ断片は正確に1増加します。 -
stream_data_message.dataPublish Messageと同じエンコーディングルールMessageDataを使用します。
データを加入者に届けずにストリームをアクティブに保つには、stream_id設定のまま送信stream_data_message。
ストリーミングメッセージ終了
配信を終了するには、 stream_end_message.stream_idを設定します。
アプリケーション定義エラーでストリームを終了するには、 stream_end_message.errorを設定します。
-
stream_end_message.error.messageは任意の人間が読み取れるエラーメッセージです。 -
stream_end_message.error.user_error_codeはオプションのアプリケーション定義エラーコードです。
ストリームが閉鎖されると、パブリッシャーは ストリームクローズドレスポンスを受け取ります。
カスタム イベントを送信する
暗黙的なdataType があり、これは設定した protobuf に基づいて、text、binary、または dataType のいずれかにすることができます。 受信側クライアントは dataType を利用して、コンテンツを正しく処理できます。
protobuf:event_message.data.protobuf_dataを設定した場合、暗黙的なdataTypeはprotobufです。protobuf_dataの値は、サポートされている任意の protobuf 型を指定できます。 イベント ハンドラーは protobuf でエンコードされたバイナリを受け取り、任意の protobuf SDK によって逆シリアル化できます。text:event_message.data.text_dataを設定した場合、暗黙的なdataTypeはtextです。text_dataの値は、文字列である必要があります。 イベント ハンドラーは、UTF-8 でエンコードされた文字列を受け取ります。binary:event_message.data.binary_dataを設定した場合、暗黙的なdataTypeはbinaryです。binary_dataの値はバイト配列である必要があります。 イベント ハンドラーは、生のバイナリ フレームを受け取ります。
ケース 1: テキスト データを含むイベントを送信する
event_message.data.text_data を "text data" に設定します。
アップストリーム イベント ハンドラーは、次に似た要求を受け取ります。
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
text/plain
dataType の場合、CloudEvents HTTP 要求の = は textになります。
ケース 2: protobuf データを含むイベントを送信する
次の顧客メッセージを受信したとします。
message MyMessage {
int32 value = 1;
}
event_message.data.protobuf_data を any.pack(MyMessage) に設定し、value = 1 を指定します。
アップストリーム イベント ハンドラーは、次に似た要求を受け取ります。
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
application/x-protobuf
dataType の場合、CloudEvents HTTP 要求の = は protobufになります。
データは有効な protobuf バイナリです。 次の proto および any.unpack() を使用して、逆シリアル化できます。
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
ケース 3: バイナリ データを含むイベントを送信する
send_to_group_message.binary_data を [1, 2, 3] に設定します。
アップストリーム イベント ハンドラーは、次に似た要求を受け取ります。
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
=
binary の場合、CloudEvents HTTP 要求の Content-Type は application/octet-stream です。 WebSocket フレームは、テキスト メッセージ フレームの場合の text 形式であるか、binary メッセージ フレームの場合の UTF8 でエンコードされたバイナリです。
メッセージが、記述された形式と一致していない場合、サービスによってクライアントが拒否されます。
ping
クライアントはサービスに PingMessage を送信して、Web PubSub サービスがクライアントの稼働を検出できるようにすることができます。
応答
すべての応答メッセージは、次の protobuf 形式に従います。
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;
}
}
クライアントが受信するメッセージは、 ack、 message、 system、 pong、 streamAck、 streamNack、または streamClosedのままです。
確認応答
要求に ackId が含まれている場合、サービスからは、この要求に対する確認応答が返されます。 クライアント実装では、次を含むこの ACK メカニズムを処理する必要があります。
-
asyncawait操作の ACK 応答を待機する。 - 一定の期間中に ACK 応答が受信されていない場合にタイムアウト チェックを行う。
クライアント実装では必ず、success の状態が true または false のどちらであるかを最初に確認する必要があります。
success の状態が false の場合、クライアントは error プロパティからエラーの詳細を読み取れます。
メッセージ応答
クライアントは、クライアントが参加しているグループから発行されたメッセージを受信できます。 または、サーバーが特定のクライアントまたは特定のユーザーにメッセージを送信するときに、サーバー管理ロールからメッセージを受信できます。
次のシナリオでは、常に DownstreamMessage.DataMessage メッセージが表示されます。
- メッセージがグループからのものである場合、
fromはgroupです。 メッセージがサーバーからのものである場合、fromはserverです。 - メッセージがグループからのものである場合、
groupはグループ名です。
送信者の dataType は、次のいずれかのメッセージを送信します。
-
dataTypeがtextの場合、message_response_message.data.text_dataを使用します。 -
dataTypeがbinaryの場合、message_response_message.data.binary_dataを使用します。 -
dataTypeがprotobufの場合、message_response_message.data.protobuf_dataを使用します。 -
dataTypeがjsonの場合、message_response_message.data.text_dataを使用します。また、コンテンツはシリアル化された JSON 文字列です。
グループメッセージがストリームに属している場合、 DownstreamMessage.DataMessage.stream が設定されます。
-
stream.stream_idは論理ストリーム識別子です。 -
stream.stream_sequence_idはストリーム内のメッセージのシーケンス番号です。 -
stream.end_of_streamはオプションです。trueに設定すると、メッセージはストリームの終端メッセージとなります。 -
stream.errorは任意であり、ストリームがエラーで終了した場合にのみ存在します。user_error_codeUserErrorのみ存在します。
ストリームackレスポンス
サービスは DownstreamMessage.StreamAckMessage を送り、受け入れられたストリームデータを確認し、次のストリームシーケンスIDを報告します。
-
stream_idは論理ストリーム識別子です。 -
expected_sequence_idはサービスが期待する次のストリームシーケンスIDです。
ストリームナックレスポンス
サービスはリトイブルストリームエラーのために DownstreamMessage.StreamNackMessage を送信します。
-
stream_idは論理ストリーム識別子です。 -
expected_sequence_idはサービスが期待する次のストリームシーケンスIDです。 -
nameには、InvalidSequenceIdまたはTransientErrorを指定できます。 -
messageエラーの詳細を含む。
ストリームクローズドレスポンス
パブリッシャー側のストリームが閉じられたときにサービスは送信 DownstreamMessage.StreamClosedMessage します。
-
stream_idは論理ストリーム識別子です。 -
errorストリームが通常閉鎖されている場合は省略されます。 -
error.nameStreamNotFound、Forbidden、BadRequest、InternalServerError、またはIdleTimeoutがあります。 -
error.messageエラーの詳細を含む。
システム応答
Web PubSub サービスでは、システム関連の応答をクライアントに送信することもできます。
接続済み
クライアントがサービスに接続すると、DownstreamMessage.SystemMessage.ConnectedMessage メッセージが表示されます。
Disconnected
サーバーによって接続が閉じられるとき、またはサービスによってクライアントが拒否されるとき、DownstreamMessage.SystemMessage.DisconnectedMessage メッセージを受け取ります。
Pong 応答
Web PubSub サービスは、クライアントから PongMessage を受信すると、PingMessage をクライアントに送信します。
次のステップ
これらのリソースを使用して、独自のアプリケーションの構築を開始します。