2012-03-20 19 views
10

JavaEE Webアプリケーション内では、着信メッセージを厳密に到着順に処理する必要があります。 Webappコンテナ(Tomcat 6)は、httpポートに到着するメッセージの順序を保持していると仮定します。厳密な順序でのメッセージの並行処理

私に頭痛を引き起こす原因は、これらのメッセージを内部的に処理する方法です。作業負荷を改善するために、ここでは多くのことを行う必要があるため、各メッセージの処理をThreadPoolに追加します。 XML解析、時には外部Webサービスを使用したデータの充実処理が終了したら、メッセージのJava表現を複合ストリーム処理エンジンesper.codehaus.orgにプッシュします。これはスレッドセーフです。ここでは、入射順序が最も高い要件、例えば現象の閾値を超える場合に、異なるパターンがチェックされる。

到着時に受け取った優先度ID(各サーブレットでは、メッセージごとにインクリメントされる)で処理されたすべてのメッセージをPriorityQueueに挿入するという考えがありました。

キューから要素をポーリングしているスレッド(最下位のIDがキューの先頭です)は、エスペアに挿入するために、欠落している項目をチェックしないためIDをスキップできます。私はイラストが良くうまくいくと思います:(4)すべてが意図したとおりに動作する手順(1)については

enter image description here

。しかし、ステップ(5)において、QueuePollerは、エレメント6を検索し、エレメント4は検索しない(ステップ(6)で後に挿入される)。メッセージの順序は次のようになります。 3; 6; 4.

私が試みたのは、厳密なIDの順序に従ってキューの頭をポーリングする実装を変更することでした。つまり、次のIDの要素がまだキューに挿入されていない場合は、その時点までバリアを待ちます。これは最初の10分間は機能していたようですが、おそらくキューに挿入されなかった要素が原因でハングしました。

これまで誰かが同じような問題を抱えていて、私にはいくつかのヒントがありますか?

+0

キューアイテムがサーバーに到着するとすぐに作成し、キューから順番に処理されるようにしたり、キューの処理が完了したらすぐに作成したりする方がよい場合があります。 –

+0

私が理解できないことは、出力キューの要素の順序が入力キューの順序と一致しなければならない場合、それらを順不同で処理していることです。つまり、QueuePollerが6より前に4を持つ必要がある場合は、なぜ4よりも前に6を行うのですか? – aib

+0

私はその2つについて考えましたが、同様の結果につながると思います。処理が完了したことを示すフラグを使用すると、何らかの処理がうまくいかない場合(サーバのタイムアウトなど、要素が挿入されていないという問題もあります)、同じ問題が発生する可能性があります。したがって、インジケータフラグは決してtrueに設定されません。 – matthes

答えて

3

Disruptorをチェックアウト - 高性能キューを厳密な順序で(最初に入力した - 最初の務め)

+0

くそー、私はそれについて言っていました:-) – dty

+0

OPの状況は、アイテムが処理スレッドに順不同で入り、アイテムのキーで指定された順序で処理する必要があるようです。どうやってこの問題を解決するのだろうか? –

+0

リンクをありがとう、私は間違いなくそれをチェックアウトし、私の問題を解決した場合は、戻って報告します。素早く読んだ後でも、欠けている要素を待っているのを解決していないようです。 – matthes

0

をクラスライブラリには、いくつかの有用な事前に定義された構成とともに、柔軟なスレッドプールの実装を提供します。 Executorの静的ファクトリメソッドの1つを呼び出して、スレッドプールを作成することができます。

私はExecutors.newSingleThreadExecutor()が最適だと思います。シングル・スレッド・エグゼキュータは、タスクを処理するための単一のワーカー・スレッドを作成し、予期せず終了した場合にはそれを置き換えます。タスクは、タスクキュー(FIFO、LIFO、優先順位)によって課された順序に従って順次処理されることが保証されています。

+0

しかし、実際には発注制約を満たしていますが、パフォーマンスを犠牲にしています。 –

+0

上記のコメントに記載されているように、これは他のすべてがうまくいかない場合、私が実現する最後の解決策です。多くの場合、メッセージの処理には非常にコストがかかることがあります。 – matthes

0

あなたの問題と、ダイアグラムの必要性(そのために+1)からわかるように、プライオリティキューは、あなたが望むもののための良い構築物ではありません。これは、キューが利用できなくなるのを待つのではなく、利用可能な6を提供することが完全にうれしいからです。

自分の同期コンテナをロールするときが来たと思います。

+0

私はこれを防ぐことを望んだ:(たくさんの仕事のように思える) – matthes

+0

優先度の高いキューを乱用するべきではない – aib

1

着信要求のプレースホルダーを即時に処理キューに追加できます。プレースホルダはスレッドプールによってバックグラウンドで前処理されますが、メイン処理は前処理が完了するのを待ちます。私が考えている構成はFutureです。