web-dev-qa-db-ja.com

タイムアウト期間が経過した後、TIME_WAIT接続がクリーンアップされない

サーバーの1つを新しいネットワーク接続の一定のストリームでヒットすることでストレステストしています。tcp_fin_timeoutは60に設定されているため、毎秒100リクエストのような一定のストリームを送信すると、 TIME_WAIT状態で6000(60 * 100)接続のローリング平均を確認してください。これは発生していますが、タイマーを確認するためにnetstatを調べます(-oを使用)。次のような接続が表示されます。

TIME_WAIT   timewait (0.00/0/0)

タイムアウトの期限が切れたが接続がまだハングしている場合、結局接続が不足します。これらの接続がクリーンアップされない理由を誰かが知っていますか?新しい接続の作成を停止すると、最終的には消えますが、常に新しい接続を作成していますが、そうではありませんが、カーネルがそれらをクリーンアップする機会を得ていないようです。接続の有効期限が切れたらすぐに接続を削除するために設定する必要のある他の構成オプションはありますか?

サーバーはUbuntuを実行しており、私のWebサーバーはnginxです。また、接続追跡を備えたiptablesがあります。これらのTIME_WAIT接続が存続するかどうかは不明です。

マークありがとう。

7
Mark D

私はしばしば自分自身を疑問に思っていたので、この問題は興味深いものでした。私はいくつかのテストを行い、いくつかの興味深い結果を見つけました。サーバーへの接続を1つ開いて60秒待つと、常にクリーンアップされました(0.00/0/0にはなりませんでした)。 100個の接続を開いた場合、それらも60秒後にクリーンアップされました。 101個の接続を開いた場合、あなたが月経を行った状態で接続が表示され始めます(これも以前に見たものです)。また、fin_timeoutの設定に関係なく、約120秒または2xMSL(60)が続くようです。カーネルのソースコードを少し掘り下げて、「理由」だと私が信じているものを見つけました。 「サイクル」ごとに発生するソケットリーピングの量を制限しようとするコードがあるようです。サイクル周波数自体は、HZに基づくスケールで設定されます。

linux-source-2.6.38/include/net/inet_timewait_sock.h:
     35 #define INET_TWDR_RECYCLE_SLOTS_LOG     5
     36 #define INET_TWDR_RECYCLE_SLOTS         (1 << INET_TWDR_RECYCLE_SLOTS_LOG)
     37 
     38 /*
     39  * If time > 4sec, it is "slow" path, no recycling is required,
     40  * so that we select tick to get range about 4 seconds.
     41  */
     42 #if HZ <= 16 || HZ > 4096
     43 # error Unsupported: HZ <= 16 or HZ > 4096
     44 #Elif HZ <= 32
     45 # define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     46 #Elif HZ <= 64
     47 # define INET_TWDR_RECYCLE_TICK (6 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     48 #Elif HZ <= 128
     49 # define INET_TWDR_RECYCLE_TICK (7 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     50 #Elif HZ <= 256
     51 # define INET_TWDR_RECYCLE_TICK (8 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     52 #Elif HZ <= 512
     53 # define INET_TWDR_RECYCLE_TICK (9 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     54 #Elif HZ <= 1024
     55 # define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     56 #Elif HZ <= 2048
     57 # define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     58 #else
     59 # define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
     60 #endif
     61 
     62 /* TIME_WAIT reaping mechanism. */
     63 #define INET_TWDR_TWKILL_SLOTS  8 /* Please keep this a power of 2. */
The number of slots is also set here:
     65 #define INET_TWDR_TWKILL_QUOTA 100

実際のtimewaitコードでは、引用符を使用してTIME_WAIT接続の強制終了を停止している場所を確認できます。

linux-source-2.6.38/net/ipv4/inet_timewait_sock.c:
    213 static int inet_twdr_do_twkill_work(struct inet_timewait_death_row *twdr,
    214                                     const int slot)
    215 {
...
    240                 if (killed > INET_TWDR_TWKILL_QUOTA) {
    241                         ret = 1;
    242                         break;
    243                 }

HZが何に設定されているのかについての詳細情報はこちらです: http://kerneltrap.org/node/5411 しかし、それは珍しいことではありませんそれを増やします。ただし、通常はtw_reuse/recyclingを有効にしてこのバケット/クォータメカニズムを回避するのがより一般的だと思います(これについて読んだので、混乱するようですが、HZを増やすと、はるかに安全でクリーンなソリューションになります)。私はこれを回答として投稿しましたが、それを修正するための「正しい方法」とは何かについて、ここでもっと議論があると思います。興味深い質問をありがとう!

3
polynomial

net.ipv4.tcp_fin_timeoutのデフォルトは60秒です。ソケットがこの制限よりもTIME_WAIT長く留まる傾向がある理由は、私にははっきりしていません。

tcp_tw_recycleは壊れているとのことですが、使っていないのでわかりません。おそらくtcp_tw_reuseを1に設定する必要がありますが、これによりNATで問題が発生する可能性があります。

0
Joshua Hoblitt