リアルタイム・ネットワーキング #
リアルタイム・コミュニケーションにおいて、なぜネットワークが重要なのか? #
ネットワークは、リアルタイム通信を制限する要素です。理想的な世界では、帯域幅が無限にあり、パケットは瞬時に到着します。しかし、実際にはそうではありません。ネットワークには限界があり、いつでも条件が変わる可能性があります。また、ネットワークの状態を測定・観察することも難しい問題です。ハードウェア、ソフトウェア、そしてその構成によって、さまざまな挙動を示すことがあります。
また、リアルタイムでの通信は、他の領域にはない問題です。Web制作者にとっては、ネットワークによってはWebサイトの表示が遅くなっても致命的ではありません。すべてのデータが届いていれば、ユーザーは満足です。WebRTCでは、データが遅れれば意味がありません。5秒前の電話会議の内容なんて誰も気にしません。そのため、リアルタイム通信システムを開発する際には、トレードオフの関係にならざるを得ません。制限時間は何秒か、どれだけ送れるか。
本章では、データ通信とメディア通信の両方に適用される概念を説明します。後の章では、理論的な説明にとどまらず、WebRTCのメディアサブシステムとデータサブシステムがこれらの問題をどのように解決するのかを説明します。
難しくしているネットワークの属性は何ですか? #
すべてのネットワークで効果的に機能するコードは複雑です。多くの異なる要因があり、それらがすべて微妙に影響し合います。開発者が遭遇する最も一般的な問題は以下の通りです。
帯域幅 #
帯域幅とは、特定のパスで転送できるデータの最大レートのことです。これは固定された数値ではないことを覚えておく必要があります。帯域幅は、利用者の増加(または減少)に伴い、経路に沿って変化します。
送信時間とラウンドトリップタイム #
送信時間とは、パケットが到着するまでの時間のことです。帯域幅と同様、これも一定ではありません。 送信時間は、いつでも変動する可能性があります。
伝送時間を計算するには、送信側と受信側の時計がミリ秒単位で同期している必要があります。 少しでもずれがあると、信頼性の低い伝送時間の測定になってしまいます。 WebRTCは非常に異質な環境で運用されているため、ホスト間の完全な時刻同期に頼ることはほとんど不可能です。
ラウンドトリップタイムの測定は、不完全なクロック同期の回避策です。
WebRTCのピアは、分散したクロックで動作する代わりに、自身のタイムスタンプ sendertime1
を含む特別なパケットを送信します。
協力しているピアがそのパケットを受信し、タイムスタンプを送信者に反映します。
オリジナルの送信者は、反映された時間を得ると、現在の時間 sendertime2
からタイムスタンプ sendertime1
を引きます。
この時間差を “往復伝搬遅延 “といい、より一般的にはラウンドトリップタイムといいます。
rtt = sendertime2 - sendertime1
ラウンド・トリップ・タイムの半分は、送信時間の十分な近似値と考えられます。 この回避策には欠点がないわけではありません。 この方法では、パケットの送信と受信にかかる時間が同じであることを前提としています。 しかし、携帯電話ネットワークでは、送信と受信の動作が時間的に対称でない場合があります。 お使いの携帯電話のアップロード速度は、ほとんどの場合、ダウンロード速度よりも低いことにお気づきかもしれません。
transmission_time = rtt/2
ラウンドトリップタイムの測定に関する技術的な内容は、RTCP送信者と受信者のレポートの章で詳しく説明されています。
ジッター #
ジッターとは、「伝送時間」がパケットごとに異なることです。パケットが遅延しても、すぐに到着する可能性があります。
パケットロス #
パケットロスとは、メッセージが送信中に失われることです。パケットロスは安定している場合もあれば、急激に発生する場合もあります。 これは、衛星やWi-Fiなどのネットワークの種類に起因します。衛星やWi-Fiなどのネットワークの種類に起因する場合もあれば、通信中のソフトウェアに起因する場合もあります。
最大伝送単位 #
最大伝送容量とは、1つのパケットの大きさの制限のことです。ネットワークでは、1つの巨大なメッセージを送信することはできません。プロトコルレベルでは、メッセージを複数の小さなパケットに分割する必要があるかもしれません。
MTUは、どのようなネットワーク経路をとるかによっても異なります。Path MTU Discoveryのようなプロトコルを使用して、送信可能な最大のパケットサイズを把握できます。
輻輳 (ふくそう) #
輻輳(ふくそう)とは、ネットワークの限界に達した状態のことです。これは通常、現在のルートが処理できる帯域のピークに達したことが原因です。また、ISPが設定した1時間ごとの制限のように、オペレータが課すものもあります。
輻輳は、さまざまな形で現れます。標準的な動作はありません。ほとんどの場合、輻輳状態になると、ネットワークは過剰なパケットをドロップします。他のケースでは、ネットワークはバッファリングします。これにより、パケットの送信時間が長くなります。また、ネットワークが輻輳すると、ジッターが増えることもあります。 この分野は急速に変化しており、輻輳検知のための新しいアルゴリズムはまだ開発中です。
ダイナミック #
ネットワークは非常に動的で、状況は急速に変化します。一回の通話では、何十万ものパケットを送受信することがあります。 これらのパケットは、複数のホップを経由します。これらのホップは、何百万人もの他のユーザーによって共有されます。あなたのローカルネットワークでも、HDムービーがダウンロードされたり、デバイスがソフトウェアアップデートをダウンロードしたりすることがあります。
良い通話ができるかどうかは、起動時にネットワークを測定するだけではわかりません。常に評価を行う必要があります。また、様々なネットワークのハードウェアやソフトウェアに起因する、あらゆる異なる動作に対応する必要があります。
パケットロスの解決 #
パケットロスの解決は、最も最初に解決すべき問題です。この問題を解決するには複数の方法があり、それぞれに利点があります。何を送信するのか、どの程度の遅延耐性があるのかによっても異なります。また、すべてのパケットロスが致命的なものではないことにも注意が必要です。ビデオの損失は問題にならないかもしれません、人間の目には認識できないかもしれません。しかし、ユーザーのテキストメッセージが失われることは致命的です。
例えば、10個のパケットを送信して、5個目と6個目のパケットが失われたとします。この問題を解決する方法は以下の通りです。
確認応答 (Acknowledgments) #
確認応答とは、受信者が受信したすべてのパケットを送信者に通知することです。送信者は、最終的ではないパケットに対する確認応答を2回受け取ると、パケットロスを認識します。送信者は、パケット4に対するACK
を2回受け取ると、5がまだ見られていないことがわかります。
選択的確認応答 (Selective Acknowledgments) #
選択的確認応答は、確認応答の改良版です。受信者は、複数のパケットを確認し、ギャップを送信者に通知するSACK
を送信できます。
この場合、送信者は4と7に対してSACK
を受け取ります。送信者は、5と6を再送する必要があることがわかります。
否定確認応答 (Negative Acknowledgments) #
否定確認応答は、逆の方法で問題を解決します。受信者は、受信した内容を送信者に通知するのではなく、失われた内容を送信者に通知します。今回のケースでは、パケット5とパケット6に対して「NACK」が送信されます。 送信者は、受信者が再送信を希望するパケットだけを知ることができます。
前方誤り訂正 (Forward Error Correction) #
前方誤り訂正は、パケットロスを先回りして修正する機能です。送信者は冗長なデータを送信するため、パケットロスがあっても最終的なストリームには影響しません。一般的なアルゴリズムとして リード・ソロモンエラー訂正があります。
これにより、アクノリッジの送信と処理のレイテンシーと複雑さが軽減されます。前方誤り訂正は、ネットワークの損失がゼロの場合、帯域幅の無駄になります。
ジッターの解決 #
ジッターはほとんどのネットワークに存在します。LANの中でも、多くの機器が変動するレートでデータを送信しています。ping
コマンドで他の機器にpingを打ち、ラウンドトリップレイテンシーの変動に気づくことで、ジッターを簡単に観察できます。
ジッターを解決するために、クライアントはジッターバッファーを使用します。ジッターバッファーはパケットの配信時間を安定させます。欠点は、ジッターバッファーが早く到着したパケットに若干の遅延を加えることです。 良い点は、遅く到着したパケットがジッターの原因にならないことです。 通話中に以下のようなパケット到着時間があるとします。
* time=1.46 ms
* time=1.93 ms
* time=1.57 ms
* time=1.55 ms
* time=1.54 ms
* time=1.72 ms
* time=1.45 ms
* time=1.73 ms
* time=1.80 ms
この場合は、~1.8msが良いでしょう。遅れて到着したパケットは、レイテンシーのウィンドウを使用します。早く到着したパケットは遅延し、遅く到着したパケットによって減少したウィンドウを埋めることができます。遅れて到着したパケットによって減少したウィンドウを埋めることができます。これにより、スタッタリングがなくなり、クライアントにスムーズな配信速度を提供できます。
輻輳の検出 #
輻輳を解決する前に、輻輳を検出する必要があります。輻輳を検出するには、輻輳コントローラを使用します。これは複雑なテーマであり、今でも急速に変化しています。 新しいアルゴリズムは今でも発表され、テストされています。高いレベルでは、どれも同じように動作します。輻輳制御装置は、いくつかの入力が与えられると、帯域幅の推定値を提供します。 以下のような入力が考えられます。
- パケットロス - ネットワークが輻輳するとパケットが廃棄されます。
- ジッター - ネットワーク機器がより過負荷になると、パケットがキューイングされ、時間が不安定になります。
- ラウンド・トリップ・タイム - 輻輳するとパケットの到着に時間がかかります。ジッターとは異なり、ラウンド・トリップ・タイムは増加し続けます。
- 明示的輻輳通知 - 新しいネットワークでは、輻輳を緩和するためにパケットがドロップされる危険性があるとタグ付けされることがあります。
これらの値は、通話中に継続して測定する必要があります。ネットワークの利用率は増減するため、利用可能な帯域幅は常に変化します。
輻輳の解消 #
推定帯域幅がわかったところで、送信するデータを調整する必要があります。どのように調整するかは、どのようなデータを送信するかによって異なります。
送信速度を遅くする #
データを送る速度を制限することは、輻輳を防ぐための最初の解決策です。輻輳制御装置が推定値を提示し、送信者の責任で速度制限を行います。
これは、ほとんどのデータ通信で使われている方法です。TCPのようなプロトコルでは、これはすべてオペレーティングシステムによって行われ、ユーザーや開発者にとっては完全に透過的です。
より少ない情報を送る #
場合によっては、制限値を満たすために、より少ない情報を送ることができます。また、データの到着には期限がありますので、より遅く送ることはできません。このような制約がリアルタイムメディアにはあります。
十分な帯域が確保できない場合は、送信するビデオの品質を下げることができます。そのためには、ビデオエンコーダーと輻輳制御装置の間で緊密なフィードバックループを構築する必要があります。