DataChannelってなに?

WebRTCと聞くと「ビデオ通話」のイメージが強いですが、実は映像や音声だけでなく軽いデータも送れる専用の通路があります。それが DataChannel です。チャットメッセージやAI推論の進捗、中間結果などを即時に返すのにピッタリ。HTTPよりもずっと遅延が少なく、リアルタイム性が高いのが魅力です。


使いどころ(ユースケース)

  • AI推論の途中経過を返す:長い処理を待たせず「今こんな分析中です」と小出しに通知できる
  • チャットやコマンド送信:軽いテキストデータを即座に届けたいときに便利
  • センサー情報やログのストリーミング:IoT機器のデータをほぼリアルタイムで集めたい場合
  • マルチプレイヤーゲーム:プレイヤーの位置や入力イベントを遅延なく共有

「映像や音声まではいらないけど、小さくて即時性が欲しいデータ」に最適です。


よくあるつまずき

  • 信頼性モード(reliable)にしてしまう → 再送で遅延が大きくなる
  • モバイルでアプリがバックグラウンドに回る → 接続が切れてしまう
  • STUN/TURNを設定していない → 社内ネットワークや外部から繋がらない

リアルタイム性を守るコツ

  • DataChannelを作るときに:pc.createDataChannel("dc", {ordered: false, maxRetransmits: 0})→ パケットロスは多少許容、でも遅延は最小化!
  • 定期的にping/pongを送って接続が生きているか確認
  • TURNサーバを必ず用意して、TCP/443でも通せるようにする(モバイルや企業NW対策)

Djangoとのつなぎ込み

Djangoは「シグナリング役」。フロント同士が直接やり取りできるように、Offer/AnswerやICE Candidateを仲介するだけ。実際のデータ通信はブラウザ同士で行うので低遅延。

# Django Channelsでシグナリングの受信例
class SignalingConsumer(AsyncWebsocketConsumer):
    async def receive(self, text_data):
        data = json.loads(text_data)
        # offer/answer/candidateをそのまま相手へ中継
        await self.channel_layer.group_send(
            "room1", {"type": "signal.message", "msg": data}
        )

運用でチェックすべき指標

  • RTT(往復遅延) → 数百ms以上なら遅すぎる
  • パケットロス率 → 多いと会話やデータが途切れる
  • TURN経由率 → 急に増えたらネットワーク障害の兆候

gRPCと比較した使い分け

  • DataChannelが得意:小さくて即時性が欲しいデータ(チャット、推論進捗、IoTログ、ゲームイベントなど)
  • gRPCが得意:明確なリクエスト→レスポンス形式、大きめのデータ転送、型安全なAPI設計や再利用が必要な場面
  • 使い分けの目安
    • 「数ミリ秒でも速く返したい」→ DataChannel
    • 「APIとして管理・拡張したい」→ gRPC

両者を組み合わせた構成例

例えば以下のように役割を分けるとバランスが良いです:

  1. 認証・制御 → DjangoがJWTなどで認証し、利用制御を行う
  2. リクエスト処理 → gRPCでML推論APIを呼び出し、型安全にレスポンスを取得
  3. リアルタイム配信 → WebRTC DataChannelで途中経過や最終結果をユーザーに逐次配信

この構成だと「管理や拡張性はgRPC」「ユーザー体験の速さはDataChannel」と、それぞれの強みを活かせます。


両方を組み合わせた構成例(実運用イメージ)

目的:認証はDjango、推論呼び出しはgRPC、途中経過や軽量通知はDataChannelで即時配信。

流れ(ざっくり)

  1. ブラウザが Django にログイン → 短命JWT を発行
  2. ブラウザは WebRTC接続(STUN/TURN経由)。DataChannelを開く
  3. 同時に gRPC‑Web→Envoy→MLサーバ に推論を開始(JWTをヘッダで添付)
  4. MLサーバはServer‑Streamingで結果を小分けに返却/進捗はDataChannelで即時通知
  5. 失敗時は冪等RPCのみ自動リトライ、DataChannelでユーザーに軽量エラー通知
[Browser]
  ├─ WebSocket(シグナリング) → [Django]
  ├─ DataChannel(進捗/軽量通知) ⇄ [Peer]
  └─ gRPC‑Web(推論) → [Envoy] → [ML gRPC Server]
                           ↑JWT検証

Django(JWT発行の最小例)

from datetime import datetime, timedelta, timezone
import jwt

def issue_token(request):
    now = datetime.now(timezone.utc)
    payload = {"sub": str(request.user.id),
               "exp": int((now + timedelta(minutes=5)).timestamp())}
    return JsonResponse({"token": jwt.encode(payload, SECRET, "HS256")})

gRPCサーバ(JWT検証インターセプタ例:Python)

import grpc, jwt

def auth_interceptor(SECRET):
    def intercept(method):
        def wrapper(request, context):
            md = dict(context.invocation_metadata())
            token = md.get("authorization", "").replace("Bearer ", "")
            try:
                jwt.decode(token, SECRET, algorithms=["HS256"])
            except Exception:
                context.abort(grpc.StatusCode.UNAUTHENTICATED, "bad token")
            return method(request, context)
        return wrapper
    return auth_interceptor

Envoy(要点)

  • envoy.filters.http.grpc_web を有効化
  • UpstreamはHTTP/2、max_grpc_timeoutを短めに
  • CORSで content-type, x-grpc-web, x-user-agent, authorization を許可

運用チェック

  • p95接続確立時間(WebRTC)/ p95応答時間(gRPC)
  • TURN経由率Envoyのupstreamエラー率
  • 再接続/リトライ回数(ユーザー体験に直結)

まとめ

DataChannelは「軽くて即時性が欲しいデータ」に最適。一方で、型安全なリクエスト/レスポンス処理や大きめのデータにはgRPCが向きます。両者を場面ごとに使い分けることで、安定した低遅延の仕組みを作れます。

投稿者 kojiro777

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です