SSブログ

NagleアルゴリズムとDelayed Ack問題 [TCP]



TCP の世界で、Nagle アルゴリズムと Delayed Ack が組み合わさった時の
問題は結構有名な話。

ネットワークソフトウェアエンジニアのバイブル


UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTIUNIXネットワークプログラミング〈Vol.1〉




にもしっかりと載っている。

簡単に説明しておくと、

Nagleアルゴリズム
送信データ(セグメント)をOSが溜め込む。溜め込んだデータを送信するタイミングは下記の通り。 OS(TCP)の気持ちも書いておく。
* すでに送信しているデータのAckが返るまで。
 → お、さっき送ったデータのAckを受け取ったぞ。
   じゃあ次のデータを相手に送ってやらなきゃ。
* 溜め込んでいるデータ量がMSSを超えるまで。
 → やべ、データをたくさん(量的に)溜め込みすぎた。
* タイムアウトを迎えるまで(200ms?)
 → やべ、データをたくさん(時間的に)溜め込みすぎた。


Delayed Ack
Ackの送信を遅らせる。Ackを送信するタイミングを下記の通り。 OSの気持ちも書いておく。 * Ackをpiggybackできる送信データがある。
 → 送信データがあるのでさっき受け取ったデータのAckもついでに返すよ。
* 一定量以上データを受信した。
 → そろそろAckを相手に返してやらないと相手も不安になるよね。
* タイムアウトを迎えるまで。
 → そろそろAckを相手に返してやらないと相手も不安になるよね。


この二つは、ともにネットワークに細切れのデータがポコポコ流れないように
効率化するための仕組み。
通常は、特に問題ないが、二つが組み合わさると問題が発生する場合がある。

1. マシンAのアプリaは、データを32byteのデータと96byteのデータを続けて送信。
2. マシンAのOSは、32byteのデータを即座に送信。
3. マシンAのOSは、96byteのデータの送信を即座に行わず溜め込む(Nagle)。
4. マシンBのOSは、32byteのデータを受信。
5. マシンBのアプリbは32byteのデータを受信。
  続く96byteのデータを受け取るまで待機するstateだった。
6. マシンBのOSは、32byteのデータのAckを送信しない(Delayed Ack)。
7. マシンAのOSは、96byteのデータをNagleにおけるタイムアウトを迎えるまで送信できない。

こんなフローが起こることって本当にあるの?と思うかもしれないが、
実は身近な例が HTTP POST

マシンAのアプリaは、1で32byteのHTTP POSTのRequest Headerをwriteし、
続けて96byteのRequest Bodyをwriteしたとする。

この場合、往々にして上記のケースに当てはまり、Request BodyのデータをOSは
Nagleのタイムアウトを迎えるまで待たされる。

解決策は下記の通り、

* アプリはRequest HeaderとRequest Bodyを一辺にwriteする。
つまり128byteのwriteをするか、それぞれのデータを同時にwritevする。
(想定しているOSはLinux。Windowsもきっと一緒だと思うけど、writevがあるのかは知らない。)
アプリaが、128byteのデータの塊をOSに渡してあげれば、
たいていの場合、OSは128byteのデータをいっぺんに送信するので、上記の問題は起こらない。

* Nagleアルゴリズムをオフにする
socketオプションでTCP_NODELAYを指定し、マシンA側でNagleアルゴリズムをオフにする。


HTTPの場合は、1コネクションで双方向にインタラクティブに通信することは(まず)なく、
A→Bという向きでデータが流れたら(Request)、
その後はB→Aという向きでデータが流れる(Response)
ので、Nagleはオフで良いと思う。

ちなみに、Delayed Ackをオフにする方法は、TCP_QUICKACKをsocketオプションで指定することだが、
この設定は持続的なものではなく、ユーザの計り知れないタイミングで再びDelayed Ackが有効に
なってしまうのでやめたほうが良い。




タグ:TCP Nagle 遅延Ack

人気ブログランキングへ
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。