一つのスレッドに限らPerlでI / O操作をノンブロッキングていますか?グッドデザイン?

StackOverflow https://stackoverflow.com/questions/1074713

質問

私は同期IO::Selectによってポーリングされ、多数のクライアントとサーバのソケット(サーバサービスと同様に管理されたコンポーネントに出て接続し、持続クライアント)を含むサービスを開発しようとしています。アイデアは、ワーカースレッドのプールによって生じるI / Oおよび/または要求処理ニーズに対応することでした。

Perlでスレッド間でデータを共有可能になり

sharedキーワード(threads::shared)がその限界を有する - 参照を扱う共有することができるプリミティブの中ではありません

私は、計画はポーリングの世話をして、実際に行うには、スレッドプールにまたがって、特定のselect()sに関連するハンドルを置くThreadQueueスレッドを持つように、ハンドルおよび/または共有することはできません参照を処理したことを考え出した前読み取りと書き込み。それは明らかに、実行している間、したがって、決してselectを実行しているのと同じものを、および - (私はselect()で使用される実際の記述子セットへの変更は、スレッドセーフでのみ1つのスレッドで行われますように、この設計はもちろん、なかったです。 )

それ自体が共有することはできません処理するので、今起こるだろう、そうポーリングだけでなく、読み取りと書き込みがすべてのスレッドから発生する必要があるために起こっているように見えるしていません。このため任意の回避策はありますか?私は、スレッド間の実際のシステムコールの分解に言及しています。明らかに、他の人に送られた他のスレッドと、実際に生成されたデータを持っているキューとバッファを使用する方法があります。

このような状況から生じる一つの問題は、私はselect()タイムアウトを与えなければならないことであり、十分に低いあまりを導入していない一方で、ポーリング記述子のかなり大規模なセットですべての問題が発生することはありませために十分に高いだろうことを期待します私のタイミングイベントループに待ち時間は - ポーリング処理で検出された実際のI / Oセットのメンバーシップがある場合、私は理解しない、けれども、select()は、一部の問題を軽減され、早期に返すこと。私はむしろ別のスレッドからselect()を目覚めいくつかの方法を持っていると思いますが、ハンドルを共有することができないので、私は簡単にそれを行うための方法を考えるでもそうすることで値を見ることはできません。それはとにかくselect()を覚ますために、適切なだ時に知っておくつもりは他のスレッドは何ですか?

いいえこの問題を回避する場合は、Perlでこのタイプのサービスのための良いデザインパターンは何ですか?私は、スケーラビリティと同時I / Oのかなり高い量の要件を持っており、その理由として、多くの人々がhigher-使用して、各リスニングソケットおよび/またはクライアントおよび/またはサーバ・プロセスのためのノンブロッキングルートだけではなく、産卵のスレッドを行ってきましたレベルの言語は、これらの日には、ソケットを扱うときに行うことが文句を言わないのです - Javaの土地における標準的な慣行のようなもののようだ、と誰もがシステム指向プログラミングの狭い領域外java.nio.*を気にするようです。多分それはちょうど私の印象です。とにかく、私はそのようにしたくない。

ですから、経験豊富なPerlのシステムプログラマの観点から、どのようにこのようなものを編成する必要がありますか?モノリシックI / Oスレッド+キューの純粋な労働者(非I / O)スレッド+たくさん?賢いハックのいくつかの並べ替え?私はすでに列挙されているもの以外のために外を見るために、任意のスレッドの安全性の落とし穴?良い方法はありますか?私はではなく、Perlのイディオムや実行時の特性を持つ、Cでプログラムのこの種を設計する豊富な経験を持っています。

編集:P.S.間違いなく、おそらくこれらの性能要件を持つプログラムと、このデザインは、単にPerlで書かれるべきでないことを私に発生しました。しかし、私はPerlで作ら非常に洗練されたサービスの非常に多くを参照してくださいので、私はそのことについて確認していない。

役に立ちましたか?

解決

あなたのいくつかの、より大きな設計の質問をブラケティング、私はperlのスレッド間でファイルハンドルを共有するにはいくつかのアプローチを提供することができます。

一つは、スレッドへの$clientルーチン開始渡すか、または単に新しいスレッドでそれを参照することがあります:

$client = $server_socket->accept();

threads->new(\&handle_client, $client);
async { handle_client($client) };
# $client will be closed only when all threads' references
# to it pass out of scope.

Thread::Queue設計で、1は、基礎となるFDをenqueue()ことがあります:

$q->enqueue( POSIX::dup(fileno $client) );
# we dup(2) so that $client may safely go out of scope,
# closing its underlying fd but not the duplicate thereof

async {
  my $client = IO::Handle->new_from_fd( $q->dequeue, "r+" );
  handle_client($client);
};

または1つだけのFDS独占的に使用することができ、およびPerlのselectのビットベクトル形式ます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top