ということに、(今更?)気付いたお話です。
HAを組んだ際のVIPの切り替えテストをやっているときに、高負荷時とかは切り替えに7秒ぴったりかかるケースとかがあって、7秒って何の数字だろうと疑問を持ちました。
OSは、CentOS 6.4(2.6.32-358.23.2.el6.x86_64)です。
TCP SYNの再送間隔が、1...2...4...秒になっている
で、tcpdumpを眺めていると以下のようなシーケンスです。
11:50:35.689301 IP client-host.8957 > server-host.http: Flags [S], seq 1616681830, win 14600, options [mss 1460,sackOK,TS val 889880946 ecr 0,nop,wscale 7], length 0 11:50:36.688503 IP client-host.8957 > server-host.http: Flags [S], seq 1616681830, win 14600, options [mss 1460,sackOK,TS val 889881946 ecr 0,nop,wscale 7], length 0 11:50:38.688540 IP client-host.8957 > server-host.http: Flags [S], seq 1616681830, win 14600, options [mss 1460,sackOK,TS val 889883946 ecr 0,nop,wscale 7], length 0 11:50:42.688557 IP client-host.8957 > server-host.http: Flags [S], seq 1616681830, win 14600, options [mss 1460,sackOK,TS val 889887946 ecr 0,nop,wscale 7], length 0 11:50:42.688993 IP server-host.http > client-host.8957: Flags [S.], seq 4112325498, ack 1616681831, win 14480, options [mss 1460,sackOK,TS val 346428911 ecr 889887946,nop,wscale 7], length 0
どうも、TCPのSYN再送が1, 2, 4秒の間隔で送られています。
はて、Linux Kernelのデフォルトは3, 6, 12, 24・・・秒ではなかったかな、と。
TCP SYNの再送間隔は、どこで設定しているか
"/proc/sys/net/ipv4/tcp_syn_retries" この辺でSYNの再送回数をいじる話は良く聞くのですが、1発目の3秒とかは、どこで設定しているのかというところ。
色々調べていると、LinuxカーネルのコードのTCPまわり"include/net/tcp.h"に、RTO(Retransmission Time Out)の定義値があることに気付きました。
#define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) #define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */ #define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now * used as a fallback RTO for the * initial data transmission if no * valid RTT sample has been acquired, * most likely due to retrans in 3WHS. */
初期値だから「TCP_TIMEOUT_INIT」かと。"initial RTO value"と書いてあるし。
#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */
確かに1秒になっていますね。
で、手元にちょっと古いCentOS 6.2(2.6.32-220.17.1.el6.x86_64)のサーバがあったので、こちらも "/usr/src/kernels/2.6.32-220.17.1.el6.x86_64/include/net/tcp.h" あたりを確認してみたところ、
#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */
おお、昔は3秒ですね。そうですよね。
つまりTCP再送の初期値を変更したかったら、この部分を変えてリビルドしなおしたらいいわけですね。ふむ。
("/proc/sys/net/ipv4/tcp_*"とかにそれっぽいのなかったんだよなぁ・・・。)
いつ変わったのか
Linux kernelのgitリポジトリを追っていると、
diff --git a/include/net/tcp.h b/include/net/tcp.h index cda30ea..149a415 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -122,7 +122,13 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #endif #define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) -#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */ +#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */ +#define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now + * used as a fallback RTO for the + * initial data transmission if no + * valid RTT sample has been acquired, + * most likely due to retrans in 3WHS. + */ #define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes * for local resources. ・・・・・以下省略・・・・・
このコミットで変わっていることが確認できます。2011/6のコミットです。
Linux Kernelのバージョンでいうと、3.2のタイミングで取り込まれているようです。
CentOS的に、いつバックポートされたのかは、、、わかりませんw (雑ですみません。)
↑の通り、少なくともVer.6.2では3秒で、6.4では1秒でした。
と、今日はそんなところで。それでは!=͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́
- 作者: Daniel P. Bovet,Marco Cesati,高橋浩和,杉田由美子,清水正明,高杉昌督,平松雅巳,安井隆宏
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2007/02/26
- メディア: 大型本
- 購入: 9人 クリック: 269回
- この商品を含むブログ (73件) を見る
- 作者: 高橋浩和,小田逸郎,山幡為佐久
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/11/18
- メディア: 単行本
- 購入: 14人 クリック: 197回
- この商品を含むブログ (118件) を見る