この質問が長くなることを前もってお詫びしますが、私がすでに試みたことを明確にしたかったのです。
設定:
- 4 つの t1.micro EC2 インスタンス (クライアント)
- VPC 内の 1 つの c1.medium EC2 インスタンス (サーバー) (Amazon Elastic Load Balancer (ELB) の背後)
- c1.medium で実行されている 1 つの単純な node.js サーバー (http ポート 3000 でリッスンし、単純な "hello" html 文字列を返します)
- c1.medium に対してカスタム ベンチマーク スイートを使用して分散負荷テストを実行する 4 つの node.js サーバー (各 t1.micro に 1 つ)
*クライアントとサーバーは Ubuntu を実行しており、ファイル記述子の制限は 102400 に引き上げられています。
実行ケース:
4 つのクライアントは、80,000 の要求が行われるまで、1 秒間に 400 から 1000 の範囲で n 回の接続 (単純な http get 要求) を試みます。サーバーには、「hello」で応答する前に、500、1000、2000、および 3000 ミリ秒でテストされたハード応答待ち時間 y があります。
問題:
1 秒あたりの接続数が 500 を超えると、数秒 (最大 10 または 15) の停止が発生し、サーバーはどのクライアントにも応答しなくなり、クライアントはアイドル状態のまま応答を待機します。これは一貫して正確に 31449 リクエストです。クライアントは、この時間中に保持されている ESTABLISHED 接続 (netstat を使用) の適切な量を示します。一方、サーバーは約 31550 の TIME_WAIT 接続を示しています。数秒後、サーバーによって報告されたこの数値が低下し始め、最終的にクライアントへの応答が再開されます。その後、同じ問題が後で合計リクエスト数 (例: 62198) で発生します (ただし、これは一貫性がありません)。そのポートのファイル記述子カウントも 0 に減少します。
試みられた解決策:
エフェメラル ポート範囲の拡大。デフォルトは 32768 ~ 61000、つまり約 30k でした。4 つの異なる物理クライアントからのトラフィックであるにもかかわらず、トラフィックは ELB のローカル IP を介してルーティングされるため、すべてのポートがその IP に割り当てられることに注意してください。事実上、4 つのクライアントすべてが 1 として扱われ、それぞれが完全なポート範囲を使用できるという通常予想される結果ではありません。したがって、合計 30k x 4 ポートではなく、4 つすべてが 30k に制限されます。そこで、net.ipv4.ip_local_port_range を使用してポート範囲を 1024 ~ 65535 に増やし、サーバーを再起動すると、次のことが観察されました。
- 新しいポート範囲が使用されます。1000 番台から 65000 番台までのポートが使用されていることが確認されています。
- 接続はまだ 31449 でスタックしています。
- TIME_WAIT 状態のポートの合計は、10 ~ 15 秒間 31550 付近でスタックした後、50000 まで上昇することが観察されています。
tc_fin_timeout、tcp_tw_recycle、tcp_tw_reuse などの他の tcp 構成も、互いに独立して、互いに結合して変更されましたが、大きな改善はありませんでした。tcp_tw_recycle が最も役立つようですが、クライアントのステータス結果が奇妙で間違った順序で出力され、接続がスタックしないことを保証するものではありません。また、これを有効にするのは危険なオプションであることも理解しています。
質問:
c1.medium に置かれる実サーバーがベンチマークされたときに高いベースラインを持つように、できるだけ多くの接続を持ちたいだけです。カーネルを再コンパイルしたり、サーバーを不安定にしたりする以外に、この 31449 接続の壁にぶつからないようにするには、他に何ができますか? 私は 500/s よりもはるかに高くできるはずだと感じており、ポート範囲を増やすだけである程度の改善が見られるはずだと思いましたが、明らかに他に何かが欠けています.
ありがとう!