TCP信頼性トランスポート
信頼性の高いトランスポート プロトコルとして TCP プロトコルはよく知られていますが、トランスポートの信頼性はどのようにして確保されるのでしょうか。
信頼性の高い伝送を実現するには、データの破損、損失、重複、シャードの順序不同など、多くの要因を考慮する必要があります。これらの問題を解決できなければ、信頼性の高い伝送は実現できません。
そのため、TCP は、シーケンス番号、確認応答、再送制御、接続管理、ウィンドウ制御などのメカニズムを採用して、信頼性の高い伝送を実現します。
本稿では、TCPのスライディングウィンドウ、フロー制御、輻輳制御に焦点を当てます。再送メカニズムについては、次のセクションで別途説明します。
ネットワークフロー制御
ネットワークフロー制御、あるいはネットワークトラフィック制御は、実際にはプロデューサーとコンシューマーの微妙な関係を体現したものです。おそらく、仕事や面接でこのシナリオに何度も遭遇したことがあるでしょう。プロデューサーの生産能力がコンシューマーの消費能力を大幅に上回ると、キューが際限なく大きくなります。より深刻なケースとして、RabbitMQのメッセージが大量に蓄積されると、MQサーバー全体のパフォーマンスが低下する可能性があることはご存知でしょう。TCPについても同様です。制御を怠ると、過剰なメッセージがネットワークに送信され、コンシューマーは処理能力を超えてしまいます。一方、プロデューサーは重複したメッセージを送信し続け、ネットワークのパフォーマンスに大きな影響を与えます。
この現象に対処するため、TCPは送信側が受信側の実際の受信能力に基づいて送信データ量を制御するメカニズム(フロー制御)を提供しています。受信側は受信ウィンドウを維持し、送信側は送信ウィンドウを維持します。これらのウィンドウは単一のTCP接続のみに適用され、すべての接続がウィンドウを共有するわけではないことに注意してください。
TCPは、受信ウィンドウ変数を用いてフロー制御を行います。受信ウィンドウは、送信者に利用可能なキャッシュ容量を示します。送信者は、受信側の実際の受信容量に応じて送信するデータ量を制御します。
受信ホストは送信ホストに受信可能なデータサイズを通知し、送信ホストはこの制限までデータを送信します。この制限はウィンドウサイズです。TCPヘッダーを覚えていますか?受信ウィンドウフィールドがあり、これは受信側が受信できる、または受信を希望するバイト数を示すために使用されます。
送信ホストは定期的にウィンドウプローブパケットを送信します。これは、受信ホストがまだデータを受信できるかどうかを検知するために使用されます。受信側のバッファがオーバーフローする危険がある場合、ウィンドウサイズはより小さい値に設定され、送信側に送信するデータ量を制御するよう指示します。
以下はネットワーク フロー制御図です。
ネットワーク輻輳制御
輻輳制御を導入する前に、受信ウィンドウと送信ウィンドウに加えて、輻輳ウィンドウも存在することを理解する必要があります。輻輳ウィンドウは主に、送信者が受信ウィンドウへのデータ送信を開始する速度を決定するために使用されます。したがって、輻輳ウィンドウもTCP送信者によって管理されます。送信するデータ量が少なすぎても多すぎても理想的ではないため、適切な送信データ量を決定するアルゴリズムが必要です。これが輻輳ウィンドウの概念です。
従来のネットワークフロー制御では、送信側が受信側のキャッシュをデータで埋めてしまうことを回避できましたが、ネットワーク内で何が起こっているかを把握していませんでした。通常、コンピュータネットワークは共有環境にあります。そのため、他のホスト間の通信によってネットワークが輻輳する可能性があります。
ネットワークが混雑している状態で大量のパケットが送信され続けると、遅延やパケットロスなどの問題が発生する可能性があります。この場合、TCPはデータを再送しますが、再送によってネットワークの負荷が増大し、遅延やパケットロスがさらに増加します。この悪循環に陥り、問題が深刻化し続ける可能性があります。
そのため、TCPはネットワーク上で何が起こっているかを無視することはできません。ネットワークが混雑している場合、TCPは送信するデータ量を減らすことで自らを犠牲にします。
そのため、送信側からのデータでネットワーク全体が飽和状態になるのを防ぐことを目的とした輻輳制御が提案されています。送信側が送信すべきデータ量を制御するために、TCPは輻輳ウィンドウと呼ばれる概念を定義しています。輻輳制御アルゴリズムは、ネットワークの輻輳度に応じて輻輳ウィンドウのサイズを調整し、送信側が送信するデータ量を制御します。
輻輳ウィンドウとは何ですか?送信ウィンドウとどう関係があるのですか?
輻輳ウィンドウは、送信者が送信できるデータ量を決定する、送信者によって維持される状態変数です。輻輳ウィンドウは、ネットワークの輻輳レベルに応じて動的に変化します。
送信ウィンドウとは、送信者と受信者の間で合意されたウィンドウサイズであり、受信者が受信できるデータ量を示します。輻輳ウィンドウと送信ウィンドウは関連しており、送信ウィンドウは通常、輻輳ウィンドウと受信ウィンドウの最小値、つまりswnd = min(cwnd, rwnd)となります。
輻輳ウィンドウ cwnd は次のように変化します。
ネットワークに輻輳がない場合、つまり再送タイムアウトが発生しない場合は、輻輳ウィンドウが増加します。
ネットワークに輻輳がある場合、輻輳ウィンドウは減少します。
送信者は、指定された時間内にACK確認応答パケットを受信したかどうかを観察することで、ネットワークが輻輳しているかどうかを判断します。送信者が指定された時間内にACK確認応答パケットを受信しない場合、ネットワークが輻輳していると判断されます。
輻輳ウィンドウに加えて、TCP輻輳制御アルゴリズムについても説明します。TCP輻輳制御アルゴリズムは、主に以下の3つの部分から構成されます。
スロースタート:最初は、cwnd 輻輳ウィンドウは比較的小さく、送信者はネットワークの容量にすぐに適応するために輻輳ウィンドウを指数関数的に増加させます。
混雑回避:輻輳ウィンドウが特定のしきい値を超えると、送信者は輻輳ウィンドウを線形的に増加させて輻輳ウィンドウの増加率を遅くし、ネットワークの過負荷を回避します。
高速回復:輻輳が発生した場合、送信者は輻輳ウィンドウを半分に減らし、受信した重複 ACK を通じてネットワーク回復の場所を決定するために高速回復状態に入り、その後輻輳ウィンドウを増やし続けます。
スロースタート
TCP接続が確立されると、輻輳ウィンドウcwndは最小MSS(最大セグメントサイズ)値に初期設定されます。これにより、初期送信速度は約MSS/RTTバイト/秒になります。実際に利用可能な帯域幅は通常、MSS/RTTよりもはるかに大きいため、TCPは最適な送信速度を見つけようとします。これはスロースタートによって実現できます。
スロースタートプロセスでは、輻輳ウィンドウcwndの値が1MSSに初期化され、送信されたパケットセグメントが確認応答されるたびにcwndの値が1MSSずつ増加します。つまり、cwndの値は2MSSになります。その後、パケットセグメントの送信が成功するたびにcwndの値が2倍になり、これを繰り返します。具体的な増加プロセスは次の図に示されています。
しかし、送信速度は常に増加するわけではなく、増加はいつかは止まります。では、送信速度の増加はいつ止まるのでしょうか?スロースタートでは、通常、送信速度の増加は次のいずれかの方法で停止します。
1つ目の方法は、スロースタートの送信プロセス中にパケットロスが発生した場合です。パケットロスが発生すると、TCPは送信側の輻輳ウィンドウcwndを1に設定し、スロースタートプロセスを再開します。この時点で、スロースタート閾値ssthreshという概念が導入されます。この閾値の初期値は、パケットロスが発生するcwnd値の半分です。つまり、輻輳が検出されると、ssthreshの値はウィンドウ値の半分になります。
2つ目の方法は、スロースタート閾値ssthreshの値と直接相関させることです。ssthreshの値は輻輳検出時のウィンドウ値の半分であるため、cwndがssthreshより大きい場合、ウィンドウ値が2倍になるたびにパケットロスが発生する可能性があります。したがって、cwndをssthreshに設定するのが最適です。これにより、TCPは輻輳制御モードに切り替わり、スロースタートが終了します。
スロースタートが終了する最後の方法は、3つの冗長ACKが検出された場合です。この場合、TCPは高速再送を実行し、回復状態に入ります。(3つのACKパケットが存在する理由が不明な場合は、再送メカニズムの項で別途説明します。)
混雑回避
TCP が輻輳制御状態に入ると、cwnd は輻輳しきい値 ssthresh の半分に設定されます。つまり、パケット セグメントが受信されるたびに cwnd の値を 2 倍にすることはできません。その代わりに、比較的保守的なアプローチが採用され、各送信が完了した後、cwnd の値は 1 MSS (最大パケット セグメント長) だけ増加されます。たとえば、10 個のパケット セグメントが確認されたとしても、cwnd の値は 1 MSS だけ増加します。これは線形増加モデルであり、増加には上限もあります。パケット損失が発生すると、cwnd の値は MSS に変更され、ssthresh の値は cwnd の半分に設定されます。また、3 つの冗長 ACK 応答を受信したときに MSS の増加も停止します。cwnd の値を半分にした後もまだ 3 つの冗長 ACK を受信した場合、ssthresh の値は cwnd の値の半分として記録され、高速回復状態に入ります。
高速回復
高速回復状態では、受信した冗長ACK(つまり、順序どおりに到着しないACK)ごとに、輻輳ウィンドウcwndの値が1MSSずつ増加します。これは、ネットワーク内で正常に送信されたパケットセグメントを活用して、伝送効率を最大限に向上させるためです。
失われたパケットセグメントに対するACKが到着すると、TCPはcwndの値を減少させ、輻輳回避状態に入ります。これは輻輳ウィンドウのサイズを制御し、ネットワークの輻輳のさらなる増加を防ぐためです。
輻輳制御状態後にタイムアウトが発生した場合、ネットワークの状態はより深刻になり、TCPは輻輳回避状態からスロースタート状態に移行します。この場合、輻輳ウィンドウcwndの値は最大パケットセグメント長である1MSSに設定され、スロースタート閾値ssthreshの値はcwndの半分に設定されます。これは、ネットワークが回復した後に輻輳ウィンドウのサイズを徐々に増加させ、伝送速度とネットワークの輻輳度のバランスをとることを目的としています。
まとめ
信頼性の高いトランスポートプロトコルとして、TCPはシーケンス番号、確認応答、再送制御、接続管理、およびウィンドウ制御によって信頼性の高いトランスポートを実現します。その中で、フロー制御メカニズムは、受信側の実際の受信能力に応じて送信側が送信するデータ量を制御し、ネットワークの輻輳やパフォーマンスの低下の問題を回避します。輻輳制御メカニズムは、送信側が送信するデータ量を調整することで、ネットワーク輻輳の発生を回避します。輻輳ウィンドウと送信ウィンドウの概念は互いに関連しており、送信側のデータ量は輻輳ウィンドウのサイズを動的に調整することで制御されます。スロースタート、輻輳回避、高速回復は、TCP輻輳制御アルゴリズムの3つの主要な部分であり、さまざまな戦略を通じて輻輳ウィンドウのサイズを調整し、ネットワークの容量と輻輳度に適応します。
次のセクションでは、TCPの再送メカニズムについて詳しく見ていきます。再送メカニズムは、信頼性の高い伝送を実現するためのTCPの重要な部分です。失われたデータ、破損したデータ、または遅延したデータを再送することで、信頼性の高いデータ伝送を保証します。次のセクションでは、再送メカニズムの実装原理と戦略を詳細に紹介し、分析します。どうぞお楽しみに!
投稿日時: 2025年2月24日