サーバサイドpush技術として見たときのWebsocketとServer-sent events(SSE)の特徴を整理したい。
- どちらもサーバからpushできる技術
- Websocketは双方向通信・SSEはサーバからクライアントへの単一方向通信
- SSEはただのHTTPストリーミング
- WebsocketはHTTPを拡張したプロトコル
- 主な用途、チャット・リアルタイム通知・共同編集などリアルタイム通信
ブラウザのサポート状況
- WebsocketはIE10以降のモダンブラウザが対応している
- SSEはIE,Edgeは対応していないが、polyfillで対応可能。
既存の開発スタックとの親和性
- SSEはHTTPそのものなので、ストリームレスポンスを返せるプラットフォームなら導入が容易。素のPHPでも25行で実装可能。
- Websocketは独自プロトコルなので、対応したウェブフレームワークが必要
- SSEはHTTPに対応リバースプロキシで動く。ただし、例えばnginxならX-Accel-Bufferingヘッダーやproxy_buffering offなどのbufferingをOFFにする対応は必要。
- WebsocketはWebsocketに対応したリバースプロキシが必要。大抵の有名なリバースプロキシは対応している。例えば、nginxでは数行の設定を書くだけで対応できる。
- WebsocketをCloudFlareに通すには有料のEnterpriseプランが必要
サーバから送れるデータ
- SSEはテキストのみ。バイナリを送る場合はbase64する。base64したバイナリのデータ量は33%ほど増えるが、SSEはHTTPなので同時にgzipが使える。
- Websocketはバイナリも送信できる。
- SSEはUTF-8のみ。UTF-8以外はやはりbase64する。
- Websocketは文字コードに制限がない。
チャネル
- WebsocketもSSEもチャネルを複数持てる。厳密には、SSEは「チャネル」という用語は使ってなく「event」という。
制約面
- Websocketは社内ファイアウォール・社内Proxyを超えられないケースがある。SSLにするといい。
- SSEは定期的にコメントでもいいから何かデータを送らないと、ブラウザやリバースプロキシが通信を切断したり、Herokuがタイムアウトしたりする。
- SSEはブラウザのホスト名あたりの同時接続数制限が問題になりやすい。モダンなブラウザでも1ホストに同時接続できるのは6〜13接続と意外と少ない。ブラウザのタブを複数開かれると辛い。SSE専用のサブドメインを幾つか用意する方法で回避可能
セキュリティ面
- WebsocketはSame-origin policyが無い。Cross-Site WebSocket Hijacking (CSWSH)の対策、Cross-site WebSockets Scripting (XSWS)の対策のため、Originヘッダのチェックする、Content-Security-Policyヘッダを活用しXSSしにくくしておく。
- SSEは普通のHTTP GETリクエストにするのと同じようにセキュリティを講じれば良い。もちろんSame-origin policyも適用される。
後で検討したいこと
- コネクション確立後、クライアントのIPが変化した場合の振る舞いはどうなるか?
- オンライン状況の変化による切断・再接続の振る舞いはどうか?
気づいたことがあれば追記していきたい。