
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は再利用が始まるので、いまひとつリコンパイルの必要性が分からず。これ、ソース呼んで妥当性チェックした人がいるノウハウなのかなあ
通信系プログラマとしては (スコア:2)
通信プログラムを書いてる人間としてはSO_REUSEADDRって、基本中の基本で、テスト中に
「うわ、連続してサーバあがんね、ってどうすんの。あSO_RESUSEADDRでいいのね」
って覚えるんだけど。
カーネル書き換えるより楽な気がするんだけど。
Re: (スコア:0)
> SO_REUSEADDRって、基本中の基本で
これはそういうサーバー側で、wellknown ポートが bind できないという話ではないと思います。
クライアント側で大量に TIME_WAIT となっていると、anonymous ポートが枯渇して困るから
その対策とか、そういう話じゃないでしょうか。
あるいはサーバー側だと、netstat -a の出力が長くなりすぎて状態を調べるのが面倒とかもあるかも。
Re: (スコア:0)
クライアント側で大量に TIME_WAIT となっていると、anonymous ポートが枯渇して困るから
そんな実装のクライアントいや~んなんだけど。
F5アタックの話だったりする?
Re: (スコア:0)
> そんな実装のクライアントいや~んなんだけど。
60秒以内に65536回、TCP接続を切断しにいったら確実にアウトなわけで、
1秒あたり1000コネクション強。
net.ipv4.ip_local_port_range の設定がデフォルトのままだと、
anonymous ポートは28233しかないので、1秒あたり500コネクション弱でアウト。
通常、サーバー間接続は張りっぱなしになるように設定するでしょうけど
(ここでクライアントというのは、サーバー間接続のクライアント側という意味です)、
ストーリーにある検索リンクから
過去のノウハウの名残では? (スコア:2)
tcp_tw_reuse などが追加されたのは Linux 2.6.7前後(2004年ごろ)で
それ以前の古いカーネルだと TCP_TIMEWAIT_LEN(若しくはそれに相当する定数) を短くするのはかなり効果があったはずです
今のカーネルは,当時の実装とは全く別物なので,
真面目に検証したいなら,今のカーネルだけなく,当時のカーネルソースも読むべきだと思います.
いずれにせよ,今時のカーネルは再コンパイルや再起動は不要で
ほとんどの項目が /proc か /etc/sysctl.conf 経由で動的にチューニングできます
Re: (スコア:0)
> 真面目に検証したいなら,今のカーネルだけなく,当時のカーネルソースも読むべきだと思います.
昔はどうあれ今の実装で効果が出ないならやっぱり意味ないでしょ。
Re:過去のノウハウの名残では? (スコア:1)
Re: (スコア:0)
確か、RHEL系のカーネルは、2.4の頃からTCP_TIMEWAIT_LEN関連のチューニングがデフォルトで入っていたはず。まあ、サーバ系でDDOS耐久試験があちこちでやられていたからかもしれないけれどね。新人の頃、ルーチンワークでテストをやらされていたなあ。
少なすぎる (スコア:1)
ポート番号が16ビットしかないのが悪いと思う。
ネットワーク系の仕事から遠ざかって久しいが、15年前ですら少なすぎると思っていた。
今の技術者から見たら、相当イライラさせられるんじゃないかな。
このストーリーはソケットの話 (スコア:0)
相手のIPアドレスが違えばポート番号は同じでもOKだから
Re: (スコア:0)
これ認識できていない人多いよね。
ちょっと簡単なソケットの実装ソースか模式図があると理解が進むんじゃないかと思うことはあります。
TIME_WAITの待ち時間 (スコア:0)
ネットワーク上に滞留していたパケットのためかと思ってたけど。
Linuxではどんな扱いなんだろう?
Re: (スコア:0)
> ネットワーク上に滞留していたパケットのためかと思ってたけど。
そうです。
> Linuxではどんな扱いなんだろう?
話に出ている tcp_tw_reuse は、
https://twitter.com/kosaki55tea/status/641267021443952640 [twitter.com]
> シーケンスナンバーの初期値を十分ずらしてやれば TIME-WAITなsocketを再利用しても安全
というものだそうで。
TCP_TIMEWAIT_LEN を増やすほうは、コネクションが混ざっちゃう可能性があって、
長時間滞留しているパケットがあると危険ですね。
tcp_tw_reuse の方がたぶん安全。
Re: (スコア:0)
> TCP_TIMEWAIT_LEN を増やすほうは、コネクションが混ざっちゃう可能性があって
失礼、「増やすほうは」じゃなくて、「減らすほうは」が正しい表現でした。
Re: (スコア:0)
TCPシーケンス番号予測攻撃 [wikipedia.org]を回避するためにSO_REUSEADDRに関係なくシーケンス番号をバラけさせる必要があるので「tcp_tw_reuseの方がたぶん安全」ということにはならないと思う。
どっちみちランダムにバラけさせて開始するなら、低いとはいえ被る可能性があるSO_REUSEADDRの方が危ない。
どうせ誤差レベルだし、他のメリット考えたらSO_REUSEADDRしといてもまず問題無いと思うけど。
# Node.jsとかはデフォルトでSO_REUSEADDRだったかな。
Re: (スコア:0)
> どっちみちランダムにバラけさせて開始するなら、低いとはいえ被る可能性がある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 の方が安全だっていうのが今回の話なわけです。
Re: (スコア:0)
SO_REUSEADDR と tcp_tw_reuse はごっちゃにしてたよ、申し訳ない。
だけどシーケンス番号を離してもその長さのデータがずらずら飛んできたらやっぱり衝突するはずです。
どうせ今時のボーレートならすぐにシーケンス番号は一巡してしまうんですから。
それとtcp_tw_reuseを使わない場合にもシーケンス番号はランダム化すべきです。
シーケンス番号のランダム化は昔から必要とされていたはずなのでとうぜん実装はあると思うのですが、
であればそれを使うべきであって再利用のためにちょっとずらしただけの状態でいるべきではありません。
そしてシーケンス番号がランダム化されているなら、即座に再利用するより一定の時間を開けたほうが安全でしょう。
長いほうが良いけど、そこはパフォーマンスとの兼ね合いもあるので考えて決める。
Re: (スコア:0)
> だけどシーケンス番号を離してもその長さのデータがずらずら飛んできたらやっぱり衝突するはずです。
いえ、ずらしているのは送信側のシーケンス番号なので、衝突しないことは保証されています。
もうクローズしたソケットですから、自分からデータを送信することはありませんから。
Re: (スコア:0)
> tcp_tw_reuse の方がたぶん安全。
断言する前に、パケットが通過するすべてのネットワーク機器がport のreuse を正しくハンドリングできることを確認してくださいね。
Re: (スコア:0)
検証するまでもなく断言できますよ。
もしも仮にそういう機器があれば、どちらのやり方でもトラブル出ますから、
tcp_twの方がマシっていう判断は動きません。
設定が無意味、ならなんでそんな「無意味なパラメータ」がLinuxカーネルソースに定義されてるんだ? (スコア:0)
そして、google検索先で「before->afterで効果あった」って書いている人たちは何を見ていたのか?
Re: (スコア:0)
TCP_TIMEWAIT_LEN は、FIN → TIME_WAIT → CLOSEでのTIME_WAITの時間を変更するカーネルの設定の事だろ。
これの値を小さくすることにより、FIN から CLOSE までの時間を短くして、新規にコネクションを受け付けられるまでの間隔を短くして多くさばけるようにすると。
先生のいってるのは、 sysctlで設定するだけでTIME_WAIT中の物を再利用出来、コネクションを多くさばけるようになると。
だから、sysctlで同じ事が実現出来るのに、なんでカーネルのリコンパイルをするのって話でしょ。
効果の有無についての話ではない
Re: (スコア:0)
なるほど、「Linuxカーネルの「TCP_TIMEWAIT_LEN」変更は無意味?」というこのストーリーのタイトルの
「変更は無意味?」がミスリーディングだったということで理解は正しいでしょうか。
(より簡単な方法で実現できるという意味で、「変更は無意味?」というよりは「変更は無駄な努力?」というべきかは?)
解説ありがとうございます。
日本人大好きTwitterで流布されんのが一番駄目なパティーン (スコア:0)
記事のリンク先にある通り、パラメータはとっくに外出しされてて、sysctlあたりで対処出来るってことですよね?
それならカッコよく「疑問だっ!(キリッ」だけじゃなくて、新しいノウハウを広めてやって下さい。
誰かがやらなきゃ、情報は古いままです。
特に日本はコピペエンジニアが結構いるので、英語情報当たる前に、古い日本語blogや、端的記述のTwitterを参考にしちゃいがちです。
カーネルのリコンパイルとか、パッケージのリコンパイルだとか、メンテが面倒いから、なるべくやらない方策を検討するようにして欲しいもんだ。
素人のチューニングより、デフォルトのが全体として、コスパが優れてる事が多いから。
英語ができないほうが大きいんじゃないか (スコア:0)
英語ができないやつだと日本語情報にあたりがちだからコピペプログラマーじゃなくても古い情報を引くことはある。
Re: (スコア:0)
英語理解できても、英語圏に入り浸ってないと「ここは古い」みたいな情報にありつけない可能性があるからなぁ…
ソース読むのが最強か。
プログラミング言語が冗談抜きで共通語になりうる世界。
Re: (スコア:0)
> それならカッコよく「疑問だっ!(キリッ」だけじゃなくて、新しいノウハウを広めてやって下さい。
> 誰かがやらなきゃ、情報は古いままです。
いいだしっぺの法則で、あなたが広めれば解決ですな。
# twitterで雑談しているときに有用な知見が得られたら、必ずその情報を広めなきゃいけない
# とかいう面倒くさいルールができたりしたら、みんな雑談では、くだらない話しかしなくなるよねー
Re: (スコア:0)
元コメを要約すれば、それこそコピペエンジニアのわがままポエムですもんね。
Re:日本人大好きTwitterで流布されんのが一番駄目なパティーン (スコア:1)
とか言ってるうちに、当のがちゃぴん先生が、まとめてくださいましたね。
http://togetter.com/li/871768 [togetter.com]
がちゃぴん先生に、圧倒的感謝。
文句言ってるだけで、まとめも作れない #2879368 は反省するように。
次回こそは頑張って圧倒的成長だ。
つまるところ (スコア:0)
ということでおk?
#Googleなどで「TCP_TIMEWAIT_LEN」を検索する [google.co.jp]とスラドのこの記事がトップに出てくるので、ググッて出て来た事をトレースする方々へのカウンターとして有効なのかも
Re: (スコア:0)
…と、有名な人がなんとなく考えたのでじゃあ今後はそっちをトレースかな?
って話ですね。
「計測したら変わらなかったよ。副作用もない」
ぐらい行かない限り、妥当性うんぬんは五十歩百歩ですね。
Re: (スコア:0)
いや、まとめ http://togetter.com/li/871768 [togetter.com] を読めば分かるけど、
これ、今回と同じ話が、
linux network ML http://thread.gmane.org/gmane.linux.network/244411/ [gmane.org]
で議論されてたことが発掘されて、その筋の権威の結論出てるから。
うーん (スコア:0)
こっち [ietf.org]を見ると、
-- 引用--
TIME-WAIT STATE:
Remain in the TIME-WAIT state. Restart the 2 MSL time-wait timeout.
-- 引用終わり --
とあるし、ホントはセグメント生存時間も合わせて調整すべきでは?と思うのですが。
実はRFC側が不味くて訂正必要だったりするんですかね?
Re:うーん (スコア:1)
何を言いたいのかわからないねぇ。その規格自体に「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みたいに?)
Re: (スコア:0)
ある程度の比率を保って調整すべきなんだろな~と思ってました。
確かに変更してもいいよ~とあっても、特にネットワークの場合、相手先までの経路含めて想定外なこと考えると、そこまで好き勝手な設定にしちゃ不味いだろと。
Re: (スコア:0)
>ところがジャップランドではそうならない
>どいつもこいつもが、まるで決定事項のように
某H系でJavaを書くときの、「StringBufferを使わなければならない」を思い出した。
Re: (スコア:0)
その例えで「なるほど」と思った
試験勉強だけが得意なタイプの優等生がテンプレ的に覚えて唱えて、その背景にある理由まで理解していないパターンね。
リテラル文字列だけの結合でも「使わなければならない」とか死ねと思った
Re: (スコア:0)
背景を理解していないことが、さらに弊害を生み出してて。
もう随分前にdotnetからStringBuilderを逆輸入してる(単純な足し算はこっちに変換される)のに、
「StringBufferを…」というテンプレのせいで逆に遅いコードを書いているという。
VBでも「描画のの高速化のため、PaintPictureではなくWin32のBitBltを使え」てなテンプレがあった。
しかし、その後のVBランタイムの改良でいつの間にかPaintPictureの方が速くなってたとさ。
まあ、今やVB自体過去の遺産だけど。
Re: (スコア:0)
Linuxサーバの構築をやったことがあるんだが、PATHを見直したらインストールされていないソフトウェアのインストールディレクトリ(当然、存在しない)が何個も書いてあって目眩を覚えた記憶がある。他にもカーネルやらサービスやらの頓珍漢な設定値がいくつもあったし、テスト項目一覧にはできもしないことが平然と列挙されてた。
先人の作った資料は備考欄にちゃんと「弊社製ミドルウェアほにゃららの動作に必要なため」って書いてあるのに、今回そのミドルウェアをインストールするのか吟味もしないで丸パクリして金貰ってるんだからプロパーの社員は良い商売だとしみじみ嫌になった。
Re: (スコア:0)
使わないPATHエントリごとコピペ流用なんてそれで害が出ることは滅多に無いからまだマシだよ。
Librahackで有名になったMDIS(三菱電機インフォメーションシステムズ)なんて個人情報ごとコピペしちゃう [mdis.co.jp]んだから。