Y-Ken Studio

新しもの好きのデータエンジニアが四方山話をお届けします。

SoftBank携帯とnet.ipv4.tcp_tw_recycle=1の相性が悪い本当の理由

photo by saschaaa

LinuxにおいてTIME_WAITなコネクションを減らす手法としてnet.ipv4.tcp_tw_recycle=1にするテクニックは有名です。
しかし環境によってはSoftBankに限らず問題が起きるため、利用には注意が必要です。

一体どのような問題が起きるのか、詳細に解説されたブログを見つけたので紹介します。

検証記事

記事1

kernel: TCP: time wait bucket table overflow の解消とTIME_WAITを減らすチューニングという記事では次の言及がされています。(抜粋)

サーバ側で net.ipv4.tcp_tw_recycle が有効で、クライアント側でTCPのタイムスタンプオプションが有効(Linuxの場合net.ipv4.tcp_timestamps = 1)だと、NAT/LBを超えたときにSYNを落としてしまい、接続障害になる。
ユーザー向けに使っているとSB携帯などで障害が発生してしまうようなので、使わないほうがいいかも。

記事2

net.ipv4.tcp_tw_recycleを有効にしたことでのトラブル事例として、次の言及がされています。(抜粋)

いくつかの回避手段を以下に。
  • サーバ側で net.ipv4.tcp_tw_recycle を無効にする
    • すべての元凶
    • どうやら Linux の独自機能で、ほかの OS ではやってないようだ
    • man の tcp(7)によるとデフォルト無効でそれが推奨設定なのに、 HOWTOによるとデフォルト有効で「専門技術者のアドバイスか要求がなければ、変更すべきではありません」という素敵な矛盾。ディストリビューションによっても違うかもしれんし、ほんとのデフォルトがどっちかは知らん。

    記事3

    kernelのソースコードと共にその現象が起きる理由を詳細に解説されています。(抜粋)

    今回問題になっていたのは最後のtcp_tw_recycleへの抵触だった。

    現象として発生しうるのは、以下の条件をすべて満たす場合
    • サーバ側でnet.ipv4.tcp_tw_recycleが有効
    • TCPタイムスタンプオプションを使用
    • 同一IPからの接続でセッションを跨ぐとセットされるTCPタイムスタンプの値が戻る場合がある

    最後の条件が微妙だが、TCPタイムスタンプの値としてセットされる値は起動時を起算時にしていたりと実装によって初期値は異なり、複数台のホストの場合は同一OSで全く同一タイミングで起動したりしない限りまず一致しない。
    そのため、TCPタイムスタンプオプションのフィールドを書き換えないNATやロードバランサ経由の接続の場合、セッションを跨ぐとセットされる値の増加が保証されない。

    まとめ

    様々な記事でtcp_tw_recycleを1にするノウハウが紹介されています。
    しかしLinuxではRFC1323での想定とは異なる箇所にtimestamp optionを実装しているため、利用には注意が必要ですね。Linux同士であれば使えるシーンもあるとは思いますが、特に外向きWebサーバではnet.ipv4.tcp_tw_recycle=1を使わない方が堅実です。

    補足

    fluentdのインストールマニュアル「ネットワーク関係のカーネルパラメータの最適化」にて、このパラメータを推奨する記載もありますが、Linux以外と通信を行うサーバにはこのパラメータを設定しない方が良さそうだと思います。