サービス障害時の折り返し連絡

Vonage Videoプラットフォームは、稼働中のすべてのサービスを継続的に監視しています。 メディアサーバーのクラッシュ、アーカイバの障害、放送ノードのダウン、SIPゲートウェイの問題、キャプションエンジンの障害など、内部的な障害がサービスに影響を及ぼした場合、プラットフォームの監視システムが障害を検知し、サービスの状態を更新した上で、登録済みのエンドポイントへ直ちにコールバック通知を送信します。

このガイドでは、各サービスが障害発生時にどのようなコールバックを発行するか、そのペイロードの形式、および各サービスをプログラム的に復旧する方法について説明します。

概要

サービスの中断は、以下のVonage Videoサービスのいずれかに影響を及ぼす可能性があります:

サービス 何が混乱しているのか 主要なコールバックの仕組み
セッション メディアルーターがクラッシュし、参加者の接続とストリームが切断されます サーバーサイドのセッション監視 Webhook および Client SDK イベント
アーカイブ(録音) アーカイバプロセスがクラッシュし、記録が異常終了しました アーカイブステータスのWebhook ("status": "failed")
放送 配信ノードに障害が発生し、HLS/RTMPストリームが終了しました 放送状況のWebhook ("status": "failed")
SIP通話 SIPゲートウェイが障害を起こし、通話接続が切断された セッション監視用ウェブフック callDestroyed
キャプション キャプションエンジンが故障し、ライブ文字起こしが停止しました キャプションの状態に関するWebhook ("status": "failed")

いずれの場合も、 reason コールバックのペイロード内のフィールドは 通常は に設定する。 "forceDisconnected". 障害の性質によっては、その他の理由値が表示される場合があるため、リカバリコードでは、(自身のAPI呼び出しに起因しない)予期せぬ終了をすべて、潜在的な障害として扱う必要があります。

注: このプラットフォームはまた、 障害発生前の警告 サーバーのローテーションについては(reason: "serverRotation") を通じて sessionNotification イベントをご覧ください。参照 サーバーのローテーションとセッションの移行 その具体的なシナリオの詳細については、

前提条件

サーバーサイドの障害コールバックを受信するには、 セッション監視のコールバックURL プロジェクト用です。詳しくは セッション監視 をご覧ください。

アーカイブ、放送、および字幕のステータスに関するコールバックについては、お使いの Vonage Video API プロジェクトダッシュボード.


セッションの中断

セッションをホストしているメディアルーターがクラッシュすると、そのセッションは破棄され、プラットフォームは sessionDestroyed セッション監視エンドポイントへのイベント。

コールバックのペイロード

{
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "projectId": "123456",
  "event": "sessionDestroyed",
  "reason": "forceDisconnected",
  "timestamp": 1718000050000
}

Client SDK のイベント

サーバーサイドのWebhookと並行して、クライアントはSDKを介してライフサイクルイベントを受信します:

session.on('sessionReconnecting', () => {
  // Platform is attempting automatic reconnection via session migration
  showReconnectingBanner();
});

session.on('sessionReconnected', () => {
  // Automatic recovery succeeded — no further action needed
  hideReconnectingBanner();
});

session.on('sessionDisconnected', (event) => {
  // Automatic recovery failed or is not enabled
  if (event.reason === 'networkDisconnected' || event.reason === 'networkTimedout') {
    promptUserToRejoin();
  }
});

publisher.on('streamDestroyed', (event) => {
  if (event.reason === 'networkDisconnected') {
    event.preventDefault(); // Keep the publisher element in the DOM
    retryPublish();
  }
});

ネイティブSDKの場合は、対応するデリゲートメソッドを使用してください:

  • iOS: OTSessionDelegate.sessionDidBeginReconnecting(_:) / sessionDidReconnect(_:) / sessionDidDisconnect(_:)
  • アンドロイドだ: Session.SessionListener.onReconnecting() / onReconnected() / onDisconnected()

回復

いつ sessionDisconnected ~で燃える reason: "forceDisconnected" (またはその後 sessionReconnecting タイムアウト):

  1. REST API またはサーバー SDK を使用して、新しいセッションを作成します。
  2. すべての参加者に新しいトークンを発行する。
  3. クライアントに再接続するよう通知してください。通知は、独自のシグナリングチャネル、プッシュ通知、またはIn-App Messagingのいずれかを通じて行います。
// Server-side — handle sessionDestroyed with reason "forceDisconnected"
app.post('/callbacks/vonage/session', (req, res) => {
  const { event, reason, sessionId } = req.body;

  if (event === 'sessionDestroyed' && reason === 'forceDisconnected') {
    createNewSessionAndNotifyClients(sessionId);
  }

  res.sendStatus(200);
});

ヒント もし セッション移行 が有効になっている場合、プラットフォームがセッションを自動的に復元することがあります。その場合は sessionReconnected クライアント側で障害が発生しても、手動での再接続は不要です。


アーカイブ(録画)の障害

アーカイバプロセスが記録の途中でクラッシュした場合、プラットフォームの監視システムがその障害を検出し、アーカイブを "failed"、そして登録済みのアーカイブステータスURLにステータスコールバックを送信します。

コールバックのペイロード

{
  "id": "b40ef09b-3811-4726-b508-e41a0f96c68f",
  "event": "archive",
  "status": "failed",
  "reason": "Internal server failure",
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "projectId": "123456",
  "name": "My Recording",
  "createdAt": 1718000000000,
  "duration": 0,
  "outputMode": "composed",
  "hasVideo": true,
  "hasAudio": true
}

主要な分野:

フィールド 変革がもたらす価値
status "failed"
reason "Internal server failure"
duration もしかすると 0 最初のセグメントが書き込まれる前に障害が発生した場合

回復

app.post('/callbacks/vonage/archive', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    // Start a new archive for the same session
    opentok.startArchive(sessionId, { name: 'Resumed recording' }, (err, archive) => {
      if (err) console.error('Failed to restart archive:', err);
      else console.log('New archive started:', archive.id);
    });
  }

  res.sendStatus(200);
});

注: アーカイブを再開する前に、そのセッションにまだアクティブな参加者がいることを必ず確認してください。参加者がいないセッションでアーカイブを開始すると、エラーが発生します。


放送の中断

放送ノードに障害が発生すると、HLS または RTMP ストリームは終了し、その放送は "failed". ステータスコールバックが、指定されたブロードキャストステータスURLに送信されます。

コールバックのペイロード

{
  "id": "1748b707-0a81-464c-9759-c46ad10d3734",
  "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4",
  "applicationId": 100,
  "createdAt": 1437676551000,
  "updatedAt": 1437676551000,
  "event": "broadcast",
  "group": "status",
  "resolution": "640x480",
  "streamMode" : "auto",
  "streams" : [],
  "broadcastUrls": {
    "hls" : "http://server/fakepath/playlist.m3u8",
    "hlsStatus": "error",
    "rtmp": {
      "foo": {
        "serverUrl": "rtmps://myfooserver:443/myfooapp",
        "streamName": "myfoostream",
        "status": "error"
      },
      "bar": {
        "serverUrl": "rtmp://mybarserver:443/mybarapp",
        "streamName": "mybarstream",
        "status": "error"
      }
    }
  },
  "settings": {
    "hls": {
      "dvr": false,
      "lowLatency": false
    }
  },
  "status": "failed",
  "reason": "Internal server failure"
}

回復

  1. 受け取る "failed" ステータスコールバック。
  2. クライアントがセッションに再接続するまで待ちます( connectionCreated イベント、または世論調査の参加者など)。
  3. 新しい放送を開始する:
app.post('/callbacks/vonage/broadcast', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    waitForParticipants(sessionId).then(() => {
      opentok.startBroadcast(sessionId, broadcastOptions, (err, broadcast) => {
        if (err) console.error('Failed to restart broadcast:', err);
        else notifyViewersOfNewStreamUrl(broadcast.broadcastUrls);
      });
    });
  }

  res.sendStatus(200);
});

重要だ: HLSのURLは、新しい配信が行われるたびに変更されます。ストリームを利用しているプレーヤーや下流システムについては、必ず新しいURLに更新してください。


SIP通話の障害

SIPゲートウェイの障害によりアクティブなコールレッグが切断されると、SIP接続は終了し、プラットフォームは callDestroyed セッション監視エンドポイントに、以下の方法で reason_message: "Unexpected Clearing". SIP接続の接続データには、通常、 sip 識別子。これにより、通常の参加者との接続と区別できるようになります。

コールバックのペイロード

{
  "sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
  "applicationId": "123456",
  "event": "callDestroyed",
  "reason_code":  "703",
  "reason_message": "Unexpected Clearing",
  "timestamp": 1718000050000,
  "call": {
    "id":  "<conference-id>",
    "connectionId":  "<sip-ot-connection-id>",
    "createdAt":  1470257688143
  }
}

回復

以下を調査して、SIP接続を特定する connection.data, その後、再度ダイヤルしてください:

app.post('/callbacks/vonage/session', (req, res) => {
  const { event, reason_message, connection, sessionId } = req.body;

  if (event === 'callDestroyed' && reason_message === 'Unexpected Clearing') {
    let connData = {};
    try { connData = JSON.parse(connection.data); } catch (_) {}

    if (connData.sip) {
      // Re-initiate the SIP call
      const sipUri = getSipUriForConnection(connection.id);
      opentok.dial(sessionId, token, sipUri, sipOptions, (err, call) => {
        if (err) console.error('SIP redial failed:', err);
        else console.log('SIP call re-established:', call.id);
      });
    }
  }

  res.sendStatus(200);
});

キャプションの表示不具合

字幕エンジンに障害が発生すると、ライブ文字起こしが停止し、その字幕セッションは "failed". ステータスコールバックが、キャプションのステータスURLに送信されます。

コールバックのペイロード

{
  "captionsId": "<captionsId>",
  "projectId": "<applicationId>",
  "sessionId": "<sessionId>",
  "status": "failed",
  "createdAt": 1651253477,
  "updatedAt": 1651253837,
  "duration": 360,
  "languageCode": "en-US",
  "reason": "Internal server failure",
  "provider": "aws-transcribe",
  "event": "sessionStatus"
}

回復

app.post('/callbacks/vonage/captions', (req, res) => {
  const { status, reason, sessionId } = req.body;

  if (status === 'failed' && reason === 'Internal server failure') {
    // Restart captions for the session
    fetch(`https://video.api.vonage.com/v2/project/${PROJECT_ID}/captions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${jwt}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ sessionId, token: generateToken(sessionId) })
    })
    .then(res => res.json())
    .then(data => console.log('Captions restarted:', data.captionsId))
    .catch(err => console.error('Failed to restart captions:', err));
  }

  res.sendStatus(200);
});

ベストプラクティス

  • 必ず reason フィールド、ただし、それだけに頼ってはいけません。通常、混乱には "Internal server failure", 回復ロジックでは、予期しないあらゆる事態を "failed" ステータス、または <something>Destroyed このイベントを、プラットフォームの変革をもたらす可能性のある出来事として捉える。
  • 冪等なリカバリハンドラを実装する。 コールバックは複数回配信される場合があります。リソース ID (archive.id, captionsId, session.id) 重複排除を行う。
  • 回転前の警告を表示してください。 について sessionNotification イベント(~付き) remainingTime: 3600 または 14400) では、予定されているローテーションについて事前に通知されます。これを利用して、ローテーションの前にアーカイブ、放送、字幕をスムーズに停止させ、ハード "forceDisconnected" 解約。
  • すべての障害事象を記録する 事後分析のために、全積載量で。その timestamp このフィールドは、影響の継続時間を算出するための基準値となります。
  • セッションについては、「セッション移行」を優先してください。 セッション移行を有効にすると、クライアントが正常なサーバーへ透過的に移行されるため、Media Router の障害による影響範囲が劇的に縮小されます。詳細については、以下を参照してください。 サーバーのローテーションとセッションの移行.
  • でアラートを設定する "Internal server failure" コールバック。 の急増 Internal server failure 複数のセッションにまたがる事象は、より広範囲にわたるプラットフォームの障害の初期兆候である。

関連リソース