Bayeux プロトコルの仕様について
はじめに
Pub/Sub Messagingを勉強するにあたって、Bayeuxプロトコルでの実装があるとのことだったので、Bayeux プロトコル日本語訳を読んでメモを取ってみました。
枯れた仕様(検索であまり当たらない)な気もしていますが、せっかく読んだので公開しようかと思います。
Bayeuxプロトコル概要
- Webサーバー間でメッセージを非同期にやりとりするためのプロトコル
- メッセージは名前付きチャネルを経て、ルーティング及び送達される
- サーバ <=> クライアント
- ajaxを利用したサーバープッシュ型のテクニック=「comet」
- 準拠要求
- 全てのMUST及びREQUIREDを満たし、かつ、全てのSHOULDを満たすものは、"完全準拠(unconditionally compliant)"
- 1つでもSHOULDを満たさないモノは「条件付き準拠(conditionally compliant)」
- ワード定義
HTTPプロトコル
- リクエスト/レスポンス型のプロトコル
- クライアント -> サーバー
- サーバー -> クライアント
- ステータスライン
- プロトコルバージョン
- 基本的にサーバー -> クライアントへはクライアントの要求なしに通信を走らせない
- Bayeuxでは、双方向の非同期通信を走らせるためサーバー・クライアント間で複数コネクションをサポートしている
- 通常アクセス用コネクション
- ロングポーリング用コネクション
- (MUST NOT)Bayeuxプロトコルも、サーバーが全てのアプリケーションに対して処理を行うために3本以上のコネクションをはらない
様々なルール
- (MUST) クライアントはブラウザのシングルオンポリシーを尊守しなければならない
- シングルオンポリシー = JSからはそれがダウンロードされたサーバー以外への接続は許可されない
- 2コネクション処理
- (MUST) Bayeux実装はHTTPのパイプライン処理を制御し、リクエスト順を保持して実行しなければならない
- ポーリング
- レスポンスを受け取った後、メッセージをサーバーに対して送信する
- 次のメッセージを受け取れるようにする処理
- Bayeux実装は、ロングポーリングと呼ばれる形式のポーリングをサポートする必要がある
- レスポンスを受け取った後、メッセージをサーバーに対して送信する
- 接続ネゴシエーション
- 接続の際、コネクション/認証/を交換して合意するネゴシエーションが行われる
- その際、ハンドシェークメッセージがかわされる
- クライアントの状態
-------------++------------+-------------+----------- +------------
State/Event || handshake | Timeout | Successful | Disconnect
|| request | | connect | request
|| sent | | response | sent
-------------++------------+-------------+----------- +------------
UNCONNECTED || CONNECTING | UNCONNECTED | |
CONNECTING || | UNCONNECTED | CONNECTED | UNCONNECTED
CONNECTED || | UNCONNECTED | | UNCONNECTED
-------------++------------+-------------+------------+------------
// BNF記法
alpha = lowalpha | upalpha
lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
"j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
"s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
"J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
"S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
"8" | "9"
alphanum = alpha | digit
mark = "-" | "_" | "!" | "~" | "(" | ")" | "$" | "@"
string = *( alphanum | mark | " " | "/" | "*" | "." )
token = ( alphanum | mark ) *( alphanum | mark )
integer = digit *( digit )
- チャネル
channel_name = "/" channel_segments channel_segments = channel_segment *( "/" channel_segment ) channel_segment = token
メッセージフィールド定義
| 名 | 説明 |
|---|---|
| channel | - メッセージの配送先および配送元を示す - リクエスト: 配送先 - レスポンス: 配送元 |
| supportedConnectionTypes | - /meta/handshakeへ送受信の際に利用 - どの転送タイプを用いるか決める - (MUST) long-polling,callback-polling等が存在 |
| clientId | - クライアントをユニークに識別するもの - /meta/handshake,投稿メッセージ以外の全てのメッセージに付与が必須 |
| id | 全てのメッセージに付与可能 |
| timestamp | - ISO 8601形式(YYYY-MM-DDThh:mm:ss.ss) - GMTで表記 |
| successful | -リクエストの成否 - /meta/*系のレスポンスに必須 |
| error | エラー |
メタメッセージ定義
handshake
クライアントは、/meta/handshakechannelに対してメッセージを送ることで接続ネゴシエーションを開始する
handshake request (MUST field)
| field | 説明 |
|---|---|
| channel | /meta/handshake という値 |
| version | クライアントで処理されるバージョン |
| supportedConnectionTypes | 接続タイプの文字列 |
handshake response
| field | 説明 |
|---|---|
| channel | /meta/handshake という値 |
| version | クライアントで処理されるバージョン |
| supportedConnectionTypes | クライアント・サーバー共にサポートする接続タイプ |
| clientId | クライアント固有のID |
| successful | true/false |
connect
クライアントは、/meta/connection channelにメッセージを送ることでコネクションを開始する。
connection request
| field | 説明 |
|---|---|
| channel | /meta/connection という値 |
| clientId | クライアント固有のID |
| connectionType | 接続タイプ |
connection response
| field | 説明 |
|---|---|
| channel | /meta/connection という値 |
| successful | true/false |
| clientId | クライアント固有のID |
subscribe
チャネルへの登録を行うために、/meta/subscribeにリクエストを行い、配信登録を行う。
subscribe request
| field | 説明 |
|---|---|
| channel | /meta/subscribe という値 |
| clientId | クライアント固有のID |
| subscription | 購読するチェネル名/チャネルパターン/配列 |
subscribe response
| field | 説明 |
|---|---|
| channel | /meta/subscribe という値 |
| successful | true/false |
| clientId | クライアント固有のID |
| subscription | 購読するチェネル名/チャネルパターン/配列 |
イベントメッセージ定義
イベントメッセージ投稿
channelに対して、イベントを投稿する処理のこと
publish request
| field | 説明 |
|---|---|
| channel | 投稿するchannel名 |
| data | JSONオブジェクトの形をしたメッセージ |
publish response
| field | 説明 |
|---|---|
| channel | 投稿したchannel名 |
| successful | true/false |
イベントメッセージ配信
channelからクライアントへイベントを配信する
| field | 説明 |
|---|---|
| channel | 投稿するchannel名 |
| data | JSONオブジェクトの形をしたメッセージ |
ポーリング
long-polling
特徴
- 配送すべきメッセージが届くまでコネクションをオープンにし続ける
- 伝送遅延を最小化
- フェールセーフとして、classicalな数秒ごとのポーリング処理を行う
- POSTメッセージのボディで伝送される
- 形式
application/x-www-form-urlencodedtext/json