ほとんどの 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 付近になります。
問題を解決するには?
エフェメラル ポートの数を 28232 から 63976 に増やします。
sysctl -w net.ipv4.ip_local_port_range="1024 65000"
Linux がタイムアウトになる前に TIME_WAIT ポートを再利用できるようにします。
sysctl -w net.ipv4.tcp_tw_reuse="1"
追加の IP アドレス。