パスワードを忘れた? アカウント作成
12508614 story
Linux

Linuxカーネルの「TCP_TIMEWAIT_LEN」変更は無意味? 42

ストーリー by hylom
副作用無く効果があるならそれがデフォルト値になっているのでは 部門より

Linuxカーネル界隈では有名ながちゃぴん先生こと@kosaki55tea氏が、LinuxカーネルのTCP_TIMEWAIT_LENを変更することについてその効果に疑問を呈している

TCP_TIMEWAIT_LENはTCPコネクションのステータスがTIME_WAITになった後、コネクションをCLOSEするまでの待ち時間を設定するパラメータで、多くの場合デフォルトでは60秒に設定されているようだ。Googleなどで「TCP_TIMEWAIT_LEN」を検索すると、大量のトラフィックを捌くサーバーではこの値を変更してカーネルをリコンパイルすることでパフォーマンスを改善できる、などという話が出てくるのだが、これについて@kosaki55tea氏は次のように述べ、カーネルリコンパイルは意味が無いのではとしている。

軽くソースを見た感じだと、tcp_tw_reuse をセットすると1秒で TIME_WAITのsocketは再利用が始まるので、いまひとつリコンパイルの必要性が分からず。これ、ソース呼んで妥当性チェックした人がいるノウハウなのかなあ

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • 通信プログラムを書いてる人間としてはSO_REUSEADDRって、基本中の基本で、テスト中に
    「うわ、連続してサーバあがんね、ってどうすんの。あSO_RESUSEADDRでいいのね」
    って覚えるんだけど。

    カーネル書き換えるより楽な気がするんだけど。

    • by Anonymous Coward

      > SO_REUSEADDRって、基本中の基本で

      これはそういうサーバー側で、wellknown ポートが bind できないという話ではないと思います。

      クライアント側で大量に TIME_WAIT となっていると、anonymous ポートが枯渇して困るから
      その対策とか、そういう話じゃないでしょうか。

      あるいはサーバー側だと、netstat -a の出力が長くなりすぎて状態を調べるのが面倒とかもあるかも。

      • by Anonymous Coward

        クライアント側で大量に TIME_WAIT となっていると、anonymous ポートが枯渇して困るから

        そんな実装のクライアントいや~んなんだけど。
        F5アタックの話だったりする?

        • by Anonymous Coward

          > そんな実装のクライアントいや~んなんだけど。

          60秒以内に65536回、TCP接続を切断しにいったら確実にアウトなわけで、
          1秒あたり1000コネクション強。
          net.ipv4.ip_local_port_range の設定がデフォルトのままだと、
          anonymous ポートは28233しかないので、1秒あたり500コネクション弱でアウト。

          通常、サーバー間接続は張りっぱなしになるように設定するでしょうけど
          (ここでクライアントというのは、サーバー間接続のクライアント側という意味です)、
          ストーリーにある検索リンクから

  • tcp_tw_reuse などが追加されたのは Linux 2.6.7前後(2004年ごろ)で
    それ以前の古いカーネルだと TCP_TIMEWAIT_LEN(若しくはそれに相当する定数) を短くするのはかなり効果があったはずです

    今のカーネルは,当時の実装とは全く別物なので,
    真面目に検証したいなら,今のカーネルだけなく,当時のカーネルソースも読むべきだと思います.

    いずれにせよ,今時のカーネルは再コンパイルや再起動は不要で
    ほとんどの項目が /proc か /etc/sysctl.conf 経由で動的にチューニングできます

    • by Anonymous Coward

      > 真面目に検証したいなら,今のカーネルだけなく,当時のカーネルソースも読むべきだと思います.

      昔はどうあれ今の実装で効果が出ないならやっぱり意味ないでしょ。

    • by Anonymous Coward

      確か、RHEL系のカーネルは、2.4の頃からTCP_TIMEWAIT_LEN関連のチューニングがデフォルトで入っていたはず。まあ、サーバ系でDDOS耐久試験があちこちでやられていたからかもしれないけれどね。新人の頃、ルーチンワークでテストをやらされていたなあ。

  • by Yuhki (17870) on 2015年09月09日 19時36分 (#2879440) 日記

    ポート番号が16ビットしかないのが悪いと思う。

    ネットワーク系の仕事から遠ざかって久しいが、15年前ですら少なすぎると思っていた。
    今の技術者から見たら、相当イライラさせられるんじゃないかな。

    • 相手のIPアドレスが違えばポート番号は同じでもOKだから

      • by Anonymous Coward

        これ認識できていない人多いよね。
        ちょっと簡単なソケットの実装ソースか模式図があると理解が進むんじゃないかと思うことはあります。

  • by Anonymous Coward on 2015年09月09日 17時03分 (#2879341)

    ネットワーク上に滞留していたパケットのためかと思ってたけど。
    Linuxではどんな扱いなんだろう?

    • by Anonymous Coward

      > ネットワーク上に滞留していたパケットのためかと思ってたけど。

      そうです。

      > Linuxではどんな扱いなんだろう?

      話に出ている tcp_tw_reuse は、

      https://twitter.com/kosaki55tea/status/641267021443952640 [twitter.com]
      > シーケンスナンバーの初期値を十分ずらしてやれば TIME-WAITなsocketを再利用しても安全

      というものだそうで。

      TCP_TIMEWAIT_LEN を増やすほうは、コネクションが混ざっちゃう可能性があって、
      長時間滞留しているパケットがあると危険ですね。
      tcp_tw_reuse の方がたぶん安全。

      • by Anonymous Coward

        > TCP_TIMEWAIT_LEN を増やすほうは、コネクションが混ざっちゃう可能性があって

        失礼、「増やすほうは」じゃなくて、「減らすほうは」が正しい表現でした。

      • by Anonymous Coward

        TCPシーケンス番号予測攻撃 [wikipedia.org]を回避するためにSO_REUSEADDRに関係なくシーケンス番号をバラけさせる必要があるので「tcp_tw_reuseの方がたぶん安全」ということにはならないと思う。
        どっちみちランダムにバラけさせて開始するなら、低いとはいえ被る可能性があるSO_REUSEADDRの方が危ない。
        どうせ誤差レベルだし、他のメリット考えたらSO_REUSEADDRしといてもまず問題無いと思うけど。
        # Node.jsとかはデフォルトでSO_REUSEADDRだったかな。

        • by Anonymous Coward

          > どっちみちランダムにバラけさせて開始するなら、低いとはいえ被る可能性があるSO_REUSEADDRの方が危ない。

          だいぶ誤解があるようです。
          SO_REUSEADDR と tcp_tw_reuse は全然違う動作をします。

          そもそも、SO_REUSEADDR は、TIME_WAIT で ip_local_port_range が満杯になっている時には効きません。
          効くのは、local port の自動割り当て時ではなく、bind(2) で明示的にポート番号を指定している場合だけです。

          また、tcp_tw_reuse は、直前に使っていたシーケンス番号から 65535 + 2 だけ離してから再使用するので、
          被ることがないことが保証されてます。

          だから、被る可能性がある TCP_TIMEWAIT_LEN よりも、tcp_tw_reuse の方が安全だっていうのが今回の話なわけです。

          • by Anonymous Coward

            SO_REUSEADDR と tcp_tw_reuse はごっちゃにしてたよ、申し訳ない。
            だけどシーケンス番号を離してもその長さのデータがずらずら飛んできたらやっぱり衝突するはずです。
            どうせ今時のボーレートならすぐにシーケンス番号は一巡してしまうんですから。

            それとtcp_tw_reuseを使わない場合にもシーケンス番号はランダム化すべきです。
            シーケンス番号のランダム化は昔から必要とされていたはずなのでとうぜん実装はあると思うのですが、
            であればそれを使うべきであって再利用のためにちょっとずらしただけの状態でいるべきではありません。

            そしてシーケンス番号がランダム化されているなら、即座に再利用するより一定の時間を開けたほうが安全でしょう。
            長いほうが良いけど、そこはパフォーマンスとの兼ね合いもあるので考えて決める。

            • by Anonymous Coward

              > だけどシーケンス番号を離してもその長さのデータがずらずら飛んできたらやっぱり衝突するはずです。

              いえ、ずらしているのは送信側のシーケンス番号なので、衝突しないことは保証されています。
              もうクローズしたソケットですから、自分からデータを送信することはありませんから。

      • by Anonymous Coward

        > tcp_tw_reuse の方がたぶん安全。

        断言する前に、パケットが通過するすべてのネットワーク機器がport のreuse を正しくハンドリングできることを確認してくださいね。

        • by Anonymous Coward

          検証するまでもなく断言できますよ。
          もしも仮にそういう機器があれば、どちらのやり方でもトラブル出ますから、
          tcp_twの方がマシっていう判断は動きません。

  • そして、google検索先で「before->afterで効果あった」って書いている人たちは何を見ていたのか?

    • by Anonymous Coward

      TCP_TIMEWAIT_LEN は、FIN → TIME_WAIT → CLOSEでのTIME_WAITの時間を変更するカーネルの設定の事だろ。
      これの値を小さくすることにより、FIN から CLOSE までの時間を短くして、新規にコネクションを受け付けられるまでの間隔を短くして多くさばけるようにすると。
      先生のいってるのは、 sysctlで設定するだけでTIME_WAIT中の物を再利用出来、コネクションを多くさばけるようになると。
      だから、sysctlで同じ事が実現出来るのに、なんでカーネルのリコンパイルをするのって話でしょ。
      効果の有無についての話ではない

      • by Anonymous Coward

        なるほど、「Linuxカーネルの「TCP_TIMEWAIT_LEN」変更は無意味?」というこのストーリーのタイトルの
        変更は無意味?」がミスリーディングだったということで理解は正しいでしょうか。
        (より簡単な方法で実現できるという意味で、「変更は無意味?」というよりは「変更は無駄な努力?」というべきかは?)
        解説ありがとうございます。

  • 記事のリンク先にある通り、パラメータはとっくに外出しされてて、sysctlあたりで対処出来るってことですよね?

    それならカッコよく「疑問だっ!(キリッ」だけじゃなくて、新しいノウハウを広めてやって下さい。
    誰かがやらなきゃ、情報は古いままです。
    特に日本はコピペエンジニアが結構いるので、英語情報当たる前に、古い日本語blogや、端的記述のTwitterを参考にしちゃいがちです。

    カーネルのリコンパイルとか、パッケージのリコンパイルだとか、メンテが面倒いから、なるべくやらない方策を検討するようにして欲しいもんだ。
    素人のチューニングより、デフォルトのが全体として、コスパが優れてる事が多いから。

    • 英語ができないやつだと日本語情報にあたりがちだからコピペプログラマーじゃなくても古い情報を引くことはある。

      • by Anonymous Coward

        英語理解できても、英語圏に入り浸ってないと「ここは古い」みたいな情報にありつけない可能性があるからなぁ…
        ソース読むのが最強か。
        プログラミング言語が冗談抜きで共通語になりうる世界。

    • by Anonymous Coward

      > それならカッコよく「疑問だっ!(キリッ」だけじゃなくて、新しいノウハウを広めてやって下さい。
      > 誰かがやらなきゃ、情報は古いままです。

      いいだしっぺの法則で、あなたが広めれば解決ですな。

      # twitterで雑談しているときに有用な知見が得られたら、必ずその情報を広めなきゃいけない
      # とかいう面倒くさいルールができたりしたら、みんな雑談では、くだらない話しかしなくなるよねー

  • by Anonymous Coward on 2015年09月09日 22時43分 (#2879548)
    • TIME_WAITがCLOSEされるまでの時間を短くするよりソケットを再利用させるほうが良い
    • TIME_WAITがCLOSEされるまでの時間を短くするにしてもsysctlで出来るので、カーネルの再コンパイルは牛刀割鶏

    ということでおk?

    #Googleなどで「TCP_TIMEWAIT_LEN」を検索する [google.co.jp]とスラドのこの記事がトップに出てくるので、ググッて出て来た事をトレースする方々へのカウンターとして有効なのかも

    • by Anonymous Coward

      …と、有名な人がなんとなく考えたのでじゃあ今後はそっちをトレースかな?
      って話ですね。

      軽くソースを見た感じだと、…
      これ、ソース呼んで妥当性チェックした人がいるノウハウなのかなあ

      「計測したら変わらなかったよ。副作用もない」
      ぐらい行かない限り、妥当性うんぬんは五十歩百歩ですね。

  • by Anonymous Coward on 2015年09月09日 23時39分 (#2879575)

    こっち [ietf.org]を見ると、
    -- 引用--
    TIME-WAIT STATE:
    Remain in the TIME-WAIT state. Restart the 2 MSL time-wait timeout.
    -- 引用終わり --
    とあるし、ホントはセグメント生存時間も合わせて調整すべきでは?と思うのですが。
    実はRFC側が不味くて訂正必要だったりするんですかね?

    • by jzkey (47353) on 2015年09月10日 1時23分 (#2879625)

      何を言いたいのかわからないねぇ。その規格自体に「For this specification the MSL is taken to be 2 minutes. This is an engineering choice, and may be changed if experience indicates it is desirable to do so」とあるわけで。
      それとも、TIME_WAITを直接変更するのではなく、MSLを変更するAPIの方が好ましいっていう意味?(FreeBSDのnet.inet.tcp.mslみたいに?)

      親コメント
      • by Anonymous Coward

        ある程度の比率を保って調整すべきなんだろな~と思ってました。
        確かに変更してもいいよ~とあっても、特にネットワークの場合、相手先までの経路含めて想定外なこと考えると、そこまで好き勝手な設定にしちゃ不味いだろと。

typodupeerror

未知のハックに一心不乱に取り組んだ結果、私は自然の法則を変えてしまった -- あるハッカー

読み込み中...