を介して同期的にポーリングされる多数のクライアントおよびサーバーソケット(サーバーサービス、および管理対象コンポーネントに接続して永続化するクライアント)を含むサービスを開発しようとしていますIO::Select
。アイデアは、ワーカースレッドのプールを通じて発生するI/Oおよび/または要求処理のニーズを処理することでした。
Perl()のshared
スレッド間でデータを共有可能にするキーワードにはthreads::shared
制限があります。ハンドル参照は、共有できるプリミティブの中にはありません。
ハンドルやハンドル参照を共有できないことを理解する前にselect()
、ポーリングを処理するスレッドを作成し、関連するハンドルをThreadQueue
スレッドプール全体に分散させて、実際に読み取りと書き込みを行う計画でした。 。(もちろん、によって使用される実際の記述子セットへの変更select
がスレッドセーフであり、1つのスレッドでのみ行われるようにこれを設計していました-実行されるのと同じスレッドであるselect()
ため、実行中は明らかになりません。)
ハンドル自体を共有できないため、これは今は発生しないようです。したがって、ポーリングと読み取りおよび書き込みはすべて1つのスレッドから実行する必要があります。これに対する回避策はありますか?スレッド間での実際のシステムコールの分解について言及しています。明らかに、キューとバッファを使用して、データを他のスレッドで生成し、実際に他のスレッドに送信する方法があります。
この状況から発生する問題の1つはselect()
、タイムアウトを指定する必要があることです。タイムアウトは、かなり大きな記述子のセットのポーリングで問題が発生しないように十分に高く、タイミングに過度の遅延が発生しないように十分に低くなると予想されます。イベントループ-ただし、ポーリングプロセスで実際のI / Oセットメンバーシップが検出された場合、select()
早期に戻るため、問題が部分的に軽減されることは理解しています。別のスレッドからウェイクselect()
アップする方法が欲しいのですが、ハンドルを共有できないため、その方法を簡単に考えることも、そうすることの価値を理解することもできません。select()
とにかく目を覚ますのが適切なとき、他のスレッドは何を知るつもりですか?
回避策がない場合、Perlでのこのタイプのサービスの適切なデザインパターンは何ですか?かなり高いスケーラビリティと同時I/Oが必要です。そのため、多くの人がより高いレベルを使用しているように、リスニングソケットやクライアントおよび/またはサーバープロセスごとにスレッドを生成するだけでなく、ノンブロッキングルートを使用しました。最近のレベル言語は、ソケットを扱うときに行うことはありません。これは、Javaの世界では一種の標準的な慣習のようでありjava.nio.*
、システム指向プログラミングの狭い領域の外では誰も気にしないようです。多分それは私の印象です。とにかく、そんな風にはしたくない。
では、経験豊富なPerlシステムプログラマーの観点から、このようなものをどのように編成する必要がありますか?モノリシックI/Oスレッド+純粋なワーカー(非I / O)スレッド+多数のキュー?ある種の巧妙なハック?私がすでに列挙したものを超えて注意すべきスレッドセーフの落とし穴はありますか?より良い方法はありますか?私はこの種のプログラムをCで設計した豊富な経験がありますが、Perlのイディオムや実行時の特性は持っていません。
編集:PSおそらく、これらのパフォーマンス要件を備えたプログラムとこの設計は、Perlで記述されるべきではないことに気づきました。しかし、Perlで作成された非常に洗練されたサービスが非常にたくさんあるので、それについてはよくわかりません。