7

C で作成するデーモンがあり、20 ~ 150K の TCP 接続を同時に処理する必要があります。それらは長時間実行される接続であり、切断されることはめったにありません。それらは常に非常に少量のデータを送信しますが (スティミュラス/レスポンス プロトコルであっても、MTU を超えることはめったにありません)、それらに対する応答時間は非常に重要です。現在の UNIX コミュニティは、大量のソケットを取得するために何を使用しており、それらの応答の待ち時間を最小限に抑えているのだろうかと思っています。フォーク ワーカー プール、スレッド (接続ごと)、静的サイズのスレッド プールへの接続の多重化を中心に展開する設計を見てきました。助言がありますか?

4

6 に答える 6

7

最も簡単な提案はlibeventを使用することです。これにより、要件に準拠する単純なノンブロッキング シングルスレッド サーバーを簡単に作成できます。

各応答の処理に時間がかかる場合、またはブロック API (DB のほとんどすべてのものなど) を使用する場合は、スレッド化が必要になります。

  • 1 つの答えはワーカー スレッドです。ここでは、一連のスレッドを生成し、それぞれが何らかのキューをリッスンして動作します。必要に応じて、スレッドではなく個別のプロセスにすることもできます。主な違いは、ワーカーに何をすべきかを伝える通信メカニズムです。

  • 別の方法として、複数のスレッドを使用し、それぞれに 150K 接続の一部を提供します。それぞれに独自のプロセス ループがあり、シングル スレッドによって処理されるリッスン ポートを除いて、シングル スレッド サーバーとほとんど同じように動作します。これはコア間で負荷を分散するのに役立ちますが、ブロッキング リソースを使用すると、この特定のスレッドによって処理されるすべての接続がブロックされます。

libevent では、注意すれば 2 番目の方法を使用できます。しかし、別の方法もあります: libev。libevent ほど有名ではありませんが、特にマルチループ スキームをサポートしています。

于 2009-10-22T18:38:07.073 に答える
2

パフォーマンスが重要な場合は、マルチスレッド イベント ループソリューション (つまり、接続を処理するためのワーカー スレッドのプール) を実際に使用する必要があります。残念ながら、ほとんどの Unix プラットフォームで動作する、これを行うための抽象化ライブラリはありません (これらのイベントループ ライブラリのほとんどがそうであるように、libevent はシングル スレッドのみであることに注意してください)。

Linuxでは、ワーカースレッドのプールでエッジトリガーepollを使用することを意味します(Windowsには、マルチスレッド環境でも正常に機能するI / O完了ポートがあります-他のUnixについてはわかりません)。

ところで、Linux と Windows の I/O 完了ポートでエッジ トリガーの epoll を抽象化しようとして、いくつかの作業を行いました。http://nginetd.cmeerw.org (進行中の作業ですが、いくつかのアイデアを提供する可能性があります)。

于 2009-10-22T20:15:57.497 に答える
1

ハビエルの答えが最も理にかなっていると思います。理論をテストしたい場合は、ノードjavascriptプロジェクトをチェックしてください。

ノードは、JavaScriptをマシンコードにコンパイルするGoogleのv8エンジンに基づいており、特定のタスクではcと同じくらい高速です。また、libevに基づいており、完全に非ブロッキングになるように設計されています。つまり、スレッド間のコンテキスト切り替えについて心配する必要はありません(すべてが単一のイベントループで実行されます)。その点でerlangと非常によく似ています。

javascriptで高性能サーバーを作成することは、ノードを使用することで非常に簡単になりました。また、少しの努力で、cでカスタムコードを記述し、ノードが実際の処理を行うためにノードを呼び出すためのバインディングを作成することもできます(これを行う方法については、ノードのソースを参照してください-ドキュメントは少し大雑把です瞬間)。醜い代替手段として、カスタムcコードをアプリケーションとしてビルドし、stdin/stdoutを使用して通信することができます。

私はノードを15万以上の接続でテストしましたが、まったく問題はありません(もちろん、これらすべての接続が一度に通信する場合は、深刻なハードウェアが必要になります)。node.jsのTCP接続は平均して2〜3 kのメモリしか使用しないため、理論的には1 GBのRAMあたり350〜500kの接続を処理できます。

注-Node.jsは現在Windowsでサポートされていませんが、開発の初期段階にすぎず、ある段階で移植されると思います。

注2-ノードから呼び出しているコードがブロックされないようにする必要があります

于 2009-12-23T01:52:16.647 に答える
1

システム構成にアクセスできる場合は、やりすぎないようにし、iptables / pf / etcを設定して、 n個のデーモンインスタンス(プロセス)間で接続の負荷を分散します。これはそのままで機能します。デーモンnの性質をブロックする方法に応じて、システム上のコアの数または数倍以上にする必要があります。このアプローチは大雑把に見えますが、壊れたデーモンを処理し、必要に応じて再起動することもできます。また、サービスを中断する代わりに、新しい接続を別のプロセスセット(たとえば、新しいリリースや新しいボックスへの移行)に転送できるため、移行はスムーズになります。その上、ソースアフィニティなどのいくつかの機能を利用できます。これらの機能は、キャッシュと競合を大幅に改善するのに役立ちます。問題のあるセッションの。

システムアクセスがない場合(またはopsを気にすることができない場合)、 iptables / pf / etcの代わりにロードバランサーデーモン(オープンソースのものがたくさんあります)を使用し、上記のようにn個のサービスデーモンも使用できます。

また、このアプローチは、ポートの特権を分離するのに役立ちます。外部サービスが低いポート(<1024)でサービスを提供する必要がある場合は、特権/またはadmin / root、またはカーネルを実行しているロードバランサーのみが必要です。)

私は過去にいくつかのIPロードバランサーを作成しましたが、本番環境ではエラーが発生しやすい可能性があります。あなたはそれをサポートしてデバッグしたくありません。また、運用と管理は、外部コードよりもコードを推測する傾向があります。

于 2009-10-22T19:23:36.150 に答える