linux の TCP_DEFER_ACCEPT (サーバサイド) の挙動について
以前 (2.6.31 まで?) は以下の挙動*1。
- 最初のペイロードを受信するまで SYN_RECV ステート
TCP の仕様的にどうなの、って話はわかる。ただ、IP 層はパケットロスの可能性があるわけで、インターネットを使っていて、この挙動で問題があるとしたら、それはアプリケーションのバグだと思うけど。一方で、 LAN 上でパケットロスが (ほぼ) 起こらない前提で作ってたら困ることがあるのかなー。Ubuntu の BTS で話が出てるのは、そういうケース (特定のハードウェアロードバランサと TCP_DEFER_ACCEPT を使う Apache との相性問題)。
で、TCP_DEFER_ACCEPT の挙動は 2.6.32 で、こう変わった。
- TCP ハンドシェイクの ACK を受信したら、もう SYN-ACK を送り続けないように
- 190 秒たったら、SYN_RECV => ESTABLISHED にステート変更
- アプリケーションの accept(2) にソケットが渡される?
参考:
Bug #134274 “TCP_DEFER_ACCEPT causes random HTTP connection fail...” : Bugs : apache2 package : Ubuntu
Linux 2.6.32-rc6 [LWN.net]
netdev - [PATCH] tcp: reduce SYN-ACK retrans for TCP_DEFER_ACCEPT