2

TCP 接続を備えた 3 つの php5-fpm サーバーの前に、2 つの nginx サーバーが合計 1000reqs/秒で完全に実行されていました。1 つの nginx サーバーで十分であると考え、すべてのトラフィックをそこにリダイレクトしました。しかし、サーバーは 750 件/秒を超えるリクエストを処理できませんでした。ギガビット イーサネットがあり、合計トラフィックが 100 メガビットを超えない (Debian 6.0)

理由を見つけることができず、グーグルで調べたところ、TCPの問題に関連している可能性があることがわかりました. しかし、この接続数と帯域幅 (約 70 メガビット/秒) を変更する必要があるとは思えませんでした。その後、トラフィックの半分を別の nginx にリダイレクトし、再び 1000reqs/秒に達しました。

nginx のエラーログとアクセスログを見てきました。問題の解決策を見つけるのに役立つツールやファイルはありますか?

4

1 に答える 1

7

ほとんどの Linux ディストリビューションでは、28232 個の一時ポートが利用可能です。サーバーは、新しい接続用にプライマリ ポート (つまり、http サーバー ポート 80) を解放するために、接続ごとに 1 つのエフェメラル ポートを必要とします。

したがって、サーバーが TCP 経由で php5-fpm によって生成されたコンテンツに対して 1000 リクエスト/秒を処​​理している場合、2000 ポート/秒を割り当てているように見えます。これは実際には当てはまりません。おそらく 5% が PHP で 95% が静的 (ポート割り当てなし) であり、IIRC nginx<->php-fpm は後続のリクエストのためにポートを開いたままにします。これらの数値に影響を与える要因は多数ありますが、議論のために、1 秒あたり 1000 ポートの割り当てとしましょう。

表面的にはこれは問題のようには見えませんが、デフォルトでは、ポートはすぐに解放されず、新しい接続に使用できるようになります。この動作にはさまざまな理由があり、ここ (または他の場所) で詳述されている変更を任意に行う前に、 TCPを完全に理解することを強くお勧めします。

主に TIME_WAIT と呼ばれる接続状態 (ネットワーク内にあるまだパケットを処理するためにソケットが待機している、netstat のマニュアル ページ) は、ポートが再利用のために解放されるのを妨げています。最近の (すべての?) Linux カーネルでは、TIME_WAIT は 60 秒にハードコーディングされており、RFC793によれば、接続は最大 4 分間 TIME_WAIT に留まる可能性があります!

これは、少なくとも 1000 個のポートが少なくとも 60 秒間使用されることを意味します。現実の世界では、通過時間、キープアライブ リクエスト (複数のリクエストが同じ接続を使用する)、およびサービス ポート (nginx とバックエンド サーバーの間) を考慮する必要があります。任意に 750 ポート/秒まで下げてみましょう。

約 37 秒で、使用可能なすべてのポートが使い果たされます (28232 / 750 = 37)。ポートを解放するのに 60 秒かかるため、これは問題です。

使用中のすべてのポートを確認するには、Apache ベンチなどを実行して、チューニング対象の 1 秒あたりのリクエスト数を生成できるようにします。次に実行します。

root:~# netstat -n -t -o | grep timewait

次のような出力が得られます (ただし、さらに多くの行があります)。

tcp        0      0 127.0.0.1:40649         127.1.0.2:80            TIME_WAIT   timewait (57.58/0/0)
tcp        0      0 127.1.0.1:9000          127.0.0.1:50153         TIME_WAIT   timewait (57.37/0/0)
tcp        0      0 127.0.0.1:40666         127.1.0.2:80            TIME_WAIT   timewait (57.69/0/0)
tcp        0      0 127.0.0.1:40650         127.1.0.2:80            TIME_WAIT   timewait (57.58/0/0)
tcp        0      0 127.0.0.1:40662         127.1.0.2:80            TIME_WAIT   timewait (57.69/0/0)
tcp        0      0 127.0.0.1:40663         127.1.0.2:80            TIME_WAIT   timewait (57.69/0/0)
tcp        0      0 127.0.0.1:40661         127.1.0.2:80            TIME_WAIT   timewait (57.61/0/0)

割り当てられたポートの現在の合計:

root:~# netstat -n -t -o | wc -l

失敗したリクエストを受信して​​いる場合、番号は 28232 付近になります。

問題を解決するには?

  1. エフェメラル ポートの数を 28232 から 63976 に増やします。

    sysctl -w net.ipv4.ip_local_port_range="1024 65000"
    
  2. Linux がタイムアウトになる前に TIME_WAIT ポートを再利用できるようにします。

    sysctl -w net.ipv4.tcp_tw_reuse="1"
    
  3. 追加の IP アドレス。

于 2012-11-28T20:45:49.470 に答える