多くのブロッキングVS単一の非ブロッキングワーカー


9

接続を受け入れるHTTPサーバーがあり、ヘッダーが完全に送信されるのを何らかの方法で待機していると仮定します。それを実装する最も一般的な方法は何ですか、それ以外の長所と短所は何ですか。私はこれらのことしか考えられません:

多くのブロッキングワーカーは、次の理由で優れています。

  • それはより敏感です。
  • 新しい接続を導入する方が簡単です(ワーカーが同期リストに追加できるようになるまで外部の人が待つのではなく、自分で接続を取得します)。
  • CPU使用率は、接続数の増減に応じて自動的に(追加の作業なしで)バランスをとります。
  • CPU使用量が少ない(ブロックされたスレッドは実行ループから除外され、クライアント間をジャンプするためのロジックは必要ありません)。

単一の非ブロッキングワーカーは、次の理由で優れています。

  • より少ないメモリを使用します。
  • レイジークライアント(サーバーへの接続とヘッダーの送信が遅い、またはまったく送信しない)に対する脆弱性が低い。

おそらくお分かりのように、私の意見では、複数のワーカースレッドは全体として少し優れたソリューションのようです。それに関する唯一の問題は、そのようなサーバーを攻撃する方が簡単であることです。

編集(より多くの研究): 私がウェブで見つけたいくつかのリソース(数千のスレッドとブロッキングI / O-Javaサーバーを記述する古い方法は、 Paul Tymaによって再び(そしてより良く)新しくなりました)ブロッキングアプローチは一般により良いが私はまだ偽の接続を処理する方法を本当に知りません。

PSタスクにいくつかのライブラリまたはアプリケーションを使用することをお勧めしません。私は、それが機能するのではなく、実際にどのように機能するか、または機能する可能性があるかを知りたいと思っています。

PSS私はロジックを複数の部分に分割しており、これはHTTPヘッダーの受け入れのみを処理します。それらを処理しません。


何年も前に、書き込みが簡単だったため、I / Oをブロックするスレッドサーバーを作成しました。同僚が他の種類を書いて、それは見事に働きました。それらは、私が働いていた会社での主要な製品提供の2つの形態でした。ブロッキングシナリオの「遅延クライアント」の場合、データ受信でタイムアウトを設定できます。

回答:


4

特効薬はありません

実際には、状況によって異なります...

tl; dr-簡単な解決策、nginxを使用...

ブロッキング:

たとえば、Apacheはデフォルトで、すべての接続に対してプロセスがフォークされるブロッキングスキームを使用します。つまり、すべての接続には独自のメモリスペースが必要であり、接続数が増えると、コンテキスト切り替えのオーバーヘッドの量も増えます。しかし、利点は、接続が閉じられると、コンテキストを破棄でき、任意/すべてのメモリを簡単に取得できることです。

マルチスレッドのアプローチは、接続の数に応じてコンテキスト切り替えのオーバーヘッドが増加するという点で似ていますが、共有コンテキストではメモリ効率が向上する可能性があります。このようなアプローチの問題は、安全な方法で共有メモリを管理することが難しいことです。多くの場合、メモリ同期の問題を克服するためのアプローチには独自のオーバーヘッドが含まれます。たとえば、ロックはCPUを集中的に使用する負荷でメインスレッドを凍結する可能性があり、不変タイプを使用すると、データの不必要なコピーが大量に追加されます。

AFAIKは、ブロッキングHTTPサーバーでマルチプロセスアプローチを使用することをお勧めします。安全な方法でメモリを管理/回復する方が安全/簡単だからです。メモリの回復がプロセスの停止と同じくらい簡単な場合、ガベージコレクションは問題にはなりません。長期実行プロセス(つまりデーモン)の場合、その特性は特に重要です。

ワーカー数が少ない場合、コンテキスト切り替えのオーバーヘッドは取るに足らないものに見えるかもしれませんが、負荷が数百から数千の同時接続にスケールアップするにつれて、不利な点がより重要になります。せいぜい、コンテキストスイッチングはO(n)を存在するワーカーの数にスケーリングしますが、実際にはそれよりも悪い可能性があります。

ブロッキングを使用するサーバーがIOの高負荷に対して理想的な選択肢ではない場合でも、CPU集中型の作業には理想的であり、メッセージの受け渡しは最小限に抑えられます。

非ブロッキング:

非ブロッキングは、Node.jsやnginxのようなものです。これらは、IO集約型の負荷がかかるノードあたりの接続数を大幅に増やすことで特に知られています。基本的に、スレッド/プロセスベースのサーバーが処理できる上限に達すると、代替オプションの検討が始まりました。これは、C10K問題(10,000の同時接続を処理する機能)とも呼ばれます。

非ブロッキング非同期サーバーは通常、メインスレッドに過負荷をかけたくないため、CPU集中型の負荷を回避するように注意する必要があるという点で、ロック付きマルチスレッドアプローチと多くの特性を共有します。利点は、コンテキストの切り替えによって発生するオーバーヘッドが本質的に排除され、1つのコンテキストメッセージの受け渡しだけで問題がなくなることです。

多くのネットワーキングプロトコルでは機能しない可能性がありますが、HTTPのステートレスな性質は、非ブロッキングアーキテクチャでは特に効果的です。リバースプロキシと複数のノンブロッキングHTTPサーバーの組み合わせを使用することで、負荷が大きいノードを特定してルーティングできます。

ノードが1つしかないサーバーでも、スループットを最大化するために、セットアップでプロセッサコアごとに1つのサーバーを含めることは非常に一般的です。

どちらも:

「理想的な」ユースケースは、両方の組み合わせになります。前面のルーティングリクエスト専用のフロントのリバースプロキシ、次にブロッキングサーバーとノンブロッキングサーバーの混合。静的コンテンツ、キャッシュコンテンツ、HTMLコンテンツの提供などのIOタスクの非ブロッキング。画像/ビデオのエンコード、コンテンツのストリーミング、数値の計算、データベースの書き込みなどのCPU負荷の高いタスクのブロック

あなたの場合:

ヘッダーを確認するだけで実際にリクエストを処理しない場合、基本的に説明しているのはリバースプロキシです。そのような場合、私は間違いなく非同期のアプローチを採用します。

nginx組み込みのリバースプロキシのドキュメントを確認することをお勧めします。

余談:

私はあなたが提供したリンクから記事を読みました、そしてそれは非同期が彼らの特定の実装のための悪い選択であったことは理にかなっています。問題は1つのステートメントで要約できます。

クライアントを切り替えるときに、値/状態を保存および復元するためのコードが難しいことがわかりました

彼らは国家にふさわしいプラットフォームを構築していた。そのような場合、非同期アプローチは、コンテキストが切り替わるたびに(つまり、イベントが発生したとき)常に状態を保存/ロードする必要があることを意味します。さらに、SMTP側では、CPUを集中的に使用する多くの作業を行っています。

彼らは非同期をかなりよく理解していないようで、その結果、多くの悪い仮定をしました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.