1715284873
2024-05-09 17:54:49
分散システムでレイテンシーの問題をデバッグするときに最初にチェックするのは、 TCP_NODELAY 有効になっています。 それは私だけではありません。 私が知っている分散システム ビルダーは皆、この単純なソケット オプションを有効にすることでレイテンシの問題をすぐに解決するために何時間も費やしており、デフォルトの動作が間違っていること、そしておそらくコンセプト全体が時代遅れであることを示唆しています。
まず、何について話しているのかを明確にしましょう。 John Nagle より優れた情報源はありません RFC896 1984年から1。 まず、問題文:
小さなパケットに関連する特別な問題があります。 キーボードから発信される単一文字メッセージの送信に TCP が使用される場合、一般的な結果は、有用なデータの各バイトに対して 41 バイトのパケット (データ 1 バイト、ヘッダー 40 バイト) が送信されることになります。 この 4000% のオーバーヘッドは煩わしいものですが、負荷の軽いネットワークでは許容範囲です。
つまり、Nagle は、ネットワークからのスループットを向上させるために、TCP ヘッダーのコストをより適切に償却することに興味を持っていました。 最大 40 倍優れたスループット! これらの小さなパケットには主に 2 つの原因がありました。1 つは一度に 1 バイトずつ入力するシェルのような人間と対話するアプリケーション、もう 1 つは、多数のメッセージを介してカーネルにメッセージを滴下する不十分に実装されたプログラムです。 write 呼び出します。 これを修正するための Nagle の提案はシンプルかつ賢明でした。
シンプルでエレガントな解決策が発見されました。
解決策は、接続上で以前に送信されたデータが未確認のままである場合、新しい送信データがユーザーから到着したときに、新しい TCP セグメントの送信を禁止することです。
多くの人が Nagle のアルゴリズムについて話すとき、タイマーについて話しますが、RFC896 ではネットワーク上の往復時間以外の種類のタイマーは使用されていません。
Nagle のアルゴリズムと遅延 ACK
Nagle の素晴らしくクリーンな提案は、別の TCP 機能である遅延との相互作用が不十分でした。 ACK。 遅延の背後にある考え方 ACK これは、少なくとも送り返すデータがあるまで、パケットの確認応答の送信を遅らせることです (例: telnet セッションはユーザーの入力をエコーバックします)、またはタイマーが期限切れになるまで。 RFC813 1982年からの延期が最初に提案されているようだ ACKs:
データの受信者は、特定の状況下では確認応答の送信を控えます。その場合、後で確認応答が送信されるようにタイマーを設定する必要があります。 ただし、受信側は、他のイベントが介入してタイマー割り込みの必要性が妨げられることが合理的に推測される場合にのみこれを行う必要があります。
それはさらに形式化されます RFC1122 これら 2 つの機能間の相互作用により問題が発生します。Nagle のアルゴリズムは、次のデータの送信をブロックしています。 ACK は受信されましたが、遅延 ACK により受信が遅れています ack 応答の準備ができるまで。 パケットをいっぱいに保つのには最適ですが、遅延の影響を受けやすいパイプライン アプリケーションにはあまり適していません。
これはネーグル氏自身が何度も主張した点である。 たとえばこれでは ハッカーニュースのコメント:
それは今でもイライラします。 本当の問題は、tinygram の防止ではありません。 それは ACK の遅延と、あの愚かな固定タイマーです。 両者はほぼ同時期に、しかし独立して TCP に参入しました。 私は tinygram 防止 (Nagle アルゴリズム) を行い、Berkeley は遅延 ACK を行いました。どちらも 1980 年代初頭に行われました。 二人の組み合わせはひどいです。
システム ビルダーにとって、これはよくある状況です。システムの 2 つの合理的な機能が相互作用して、望ましくない動作を引き起こします。 この種の対話は、プロトコルの設計を非常に難しくしているものの 1 つです。
ネーグルは無罪なのか?
残念ながら、ACK の遅延だけではありません。 遅れたACKなどがなくても バカな固定タイマー、Nagle のアルゴリズムの動作は、おそらく分散システムで望むものではありません。 データセンター内の 1 つの RTT は通常約 500 マイクロ秒で、同じ地域内のデータセンター間では数ミリ秒、地球を一周すると最大で数百ミリ秒になります。 最新のサーバーがわずか数百マイクロ秒で実行できる膨大な作業量を考えると、たとえ 1 RTT でもデータ送信を遅らせても、明らかに有利とは言えません。
より明確なケースを作るために、Nagle のアルゴリズムの背後にある正当化に戻りましょう。ヘッダーのコストを償却し、シングルバイト パケットの 40 倍のオーバーヘッドを回避するというものです。 しかし、もうシングルバイトのパケットを送信する人はいないのでしょうか? ほとんどの分散データベースとシステムはそうではありません。 その理由の 1 つは、単に伝えたいことがたくさんあるためであり、一部は TLS などのプロトコルの追加のオーバーヘッドが原因であり、一部はエンコードとシリアル化のオーバーヘッドが原因です。 しかし、ほとんどの場合、彼らはもっと言いたいことがあります。
小さなメッセージを送信しないという中心的な懸念は依然として非常に現実的なものですが、私たちはそれを非常に効果的にアプリケーション層に押し込みました。 Nagle のアルゴリズムがどのような動作をするとしても、JSON でラップして一度にバイトを送信するのはあまり効率的ではありません。
ネーグルは必要ですか?
まず、議論の余地のない見解です。最新のデータセンター クラスのハードウェアで実行される遅延に敏感な分散システムを構築している場合は、 TCP_NODELAY (Nagle のアルゴリズムを無効にしても) 心配する必要はありません。 気分を悪くする必要はありません。 それは罪ではありません。 大丈夫です。 どうぞ。
さらに物議を醸しているのは、トラフィックとアプリケーションの組み合わせ、そして今日のハードウェアの機能を考慮すると、Nagle のアルゴリズムは現代のシステムには必要ないのではないかということです。 言い換えると、 TCP_NODELAY がデフォルトである必要があります。 そうすればいくらかはできるだろう」write 「すべてのバイト」コードはそうでない場合よりも遅くなりますが、効率を重視するのであれば、これらのアプリケーションはとにかく修正する必要があります。
脚注
#常に #TCP_NODELAY #です #毎回ね