リアルタイム通信について
リアルタイム通信・ストリーミングについてと、技術選定について
リアルタイム通信/ストリーミングを実現する方法について
各技術の通信方向・遅延・スケール特性をまとめると次の通り。
graph TD
Q1{"ミリ秒単位の<br/>超低遅延が必要?"}
Q2{"不特定多数<br/>(万〜百万規模)<br/>への同時配信?"}
Q3{"双方向通信<br/>が必要?"}
Q4{"更新頻度が<br/>秒単位以下?"}
Q5{"クライアント→サーバーの<br/>送信も必要?"}
WebRTC["WebRTC / UDP<br/>超低遅延・P2P"]
HTTP["HTTPストリーミング<br/>HLS / MPEG-DASH<br/>CDN対応・数秒遅延あり"]
WS["WebSocket<br/>双方向・サーバー中継"]
Polling["ポーリング<br/>シンプルだが非効率"]
SSE["SSE<br/>サーバー→クライアント<br/>一方向・シンプル"]
Q1 -->|Yes| WebRTC
Q1 -->|No| Q2
Q2 -->|Yes| HTTP
Q2 -->|No| Q3
Q3 -->|Yes| Q4
Q4 -->|頻度高い| WS
Q4 -->|頻度低い| Polling
Q3 -->|No| Q5
Q5 -->|必要ない| SSE
Q5 -->|必要| WS
WebSocket
チャットアプリ、オンラインゲーム、株価更新など。
普通のWebアプリなら、ほぼWebSocket一択。
サーバー中心(サーバーで状態を一元管理する方が楽&安全)で全員に配るような処理、不特定多数向けの通信に向いている。
常にサーバー経由。
サーバが中継するので、接続数増えるとサーバ負荷増える。→スケールアウト(サーバー増やす)で対応可能
後述の他の手段と比較するとバランス型と言える。
WebRTC(Web Real-Time Communication、ブラウザ間のリアルタイム通信を実現するWebAPI仕様群)
音声通話、ビデオ通話、対戦・FPSゲームなど。
実装が大変でサーバ構成も複雑。
超低遅延が必要な場合の選択肢。
WebSocketとは異なり、最初だけサーバー、その後は基本P2P(直通)
端末同士で最短距離でやり取りするような処理、ミリ秒単位の遅延を抑えたい時、1対1 / 少人数向けの通信に向いている。
配信先が増えるとP2Pの直接接続数も比例して増えてしまうので多数向けではない。
SSE(Server-Sent Events)
通知、ログ配信、進捗バー表示など。
一方向でいい場合は一番コスパがいい。
サーバー → クライアントの一方向通信で、HTTPのままストリーミング可能。
WebSocketよりシンプル。自動再接続。
クライアント → サーバーは別途HTTP必要で、双方向ではない。
1接続 = 1ストリーム(接続張りっぱなし)であり、バイナリ効率悪い(基本テキスト)のため動画みたいな大容量に不向きで、キャッシュもできないため、Youtube等には不向き。
ポーリング
クライアント側から定期的にAPIを叩くなどして更新有無をチェック メール、旧Twitter、ECサイトの注文ステータスなどに採用。
HTTPストリーミング
数秒単位で動画を分割して配信
Youtubeの場合:HLS(HTTP Live Streaming、映像を小さなセグメントに分割して配信するApple開発の動画配信規格) / MPEG-DASH(Dynamic Adaptive Streaming over HTTP、ネットワーク状況に応じて解像度を自動調整する国際標準の動画配信規格)
CDN(Content Delivery Network、コンテンツ配信ネットワーク)に乗せられ、キャッシュでき、スケールも無限に近いが、数秒遅延が発生する
独自UDP
既存のWeb技術ではリアルタイム性が不十分な場合に、独自UDP(User Datagram Protocol、高速だが信頼性保証のないトランスポート層プロトコル)プロトコルが用意される場合がある(後述)
リアルタイム性重視。その代わりに安定性を妥協
各種サービスでの利用例
基本は、
- メッセージ系 → WebSocket
- 通話系 → WebRTC
- 動画配信 → HTTPストリーミング
- ガチゲーム → UDP独自実装
LINE
WebSocket + WebRTC(併用)
- テキストチャット → WebSocket
- 通話(音声・ビデオ) → WebRTC
Slack
WebSocket + WebRTC(併用)
- 基本 → WebSocket
- 通話 → 内部的にWebRTC
Zoom / Google Meet / Microsoft Teams
WebRTC(+サーバー中継)
-
音声・映像 → WebRTC
-
接続制御 → WebSocketなど
※SFU(中継サーバー)使用
ChatGPT
SSE(Server Sent Events)
Youtube
HTTPストリーミング
- 動画(ライブ配信含む) → HLS / MPEG-DASH(HTTPベース) ※ コメント欄はWebSocket or SSE
安定性とスケーラビリティ優先のため、ライブ配信でも採用されている。 また、WebRTCは少人数向けのため不向き。
Apex Legends(FPSゲーム)
独自UDP
- ゲーム通信 → UDPベース独自プロトコル
各技術の通信方向まとめ
graph LR
subgraph WebSocket
direction LR
WC["クライアント"] <-->|双方向| WS["サーバー"]
end
subgraph WebRTC
direction LR
RC["クライアントA"] <-->|P2P直接通信| RC2["クライアントB"]
RC -.->|シグナリングのみ| RS["サーバー"]
end
subgraph SSE
direction LR
SC["クライアント"] -->|リクエスト| SS["サーバー"]
SS -->|イベントストリーム| SC
end
subgraph ポーリング
direction LR
PC["クライアント"] -->|定期リクエスト| PS["サーバー"]
PS -->|レスポンス| PC
end
技術選定時の判断フロー
※ 下記はあくまで参考
- ミリ秒単位の遅延が必要 → WebRTC/UDP
- 不特定多数(数千〜数百万)に同時配信する → HTTPストリーミング(HLS / DASH)
- 双方向通信が必要 → 更新頻度(秒単位 or それ以上)が高ければWebSocket、低ければポーリング
- サーバーからクライアントへの一方向 → 更新頻度は数秒以内ならSSE、数十秒〜分単位でOKならポーリング
- 上記以外 → WebSocket