0

EventHandler の 1 つが壊れたときに、CPU 使用率が高い状況に陥りました。

EventHanldersバッファーを介して順次実行するように構成された複数のコンシューマー ( ) があるとします。最初の EventHandler が例外をスローした場合、他のすべての EventHandler を停止する (そして後で起こす) 方法はありますか?

私たちが行っていることは、失敗したスレッドをスリープ状態にしてから、同じイベントを再度消費しようとすることです。RingBufferしかし、他のスレッドが引き続き実行され、読み取るイベントがない場合でも読み取りを試行し、CPU が許容レベルよりも低下していることに気付きました。

通常の条件下では期待どおりに動作するためWaitStrategy、これが原因で発生していることを今のところ破棄します。disruptorを使用してBlockingWaitStrategyおります。

例のためにいくつかの説明

INPUT -> [A*] -> [B] -> [C] -> [D] 

ここで、INPUT は からポーリングされたイベントでRingBuffer、A、B、C、および D は順次実行されるさまざまな EventHandler です。A* は、例外をスローする消費者です。

私たちが達成したいことは、コンシューマ A がイベントを消費できない場合 (例: 例外が発生した後)、そのコンシューマの OnEvent(...) メソッドは終了せず、再び消費を試みる通常のスリープでループにとどまることです。起きたら同じイベント。その間、他のすべてのコンシューマーは、A が成功するまでパークまたはスリープ状態にする必要があります。

ディスラプター バージョン 3.3.0 を使用しています。

私はグーグルで検索しましたが、有効な解決策が見つかりませんでした。

前もって感謝します。

サルバ。

4

1 に答える 1

0

大学は、この問題が BlockingWaitStrategy の waitFor メソッドの while ループに関連している可能性があることを発見しました。

    long availableSequence;
    while((availableSequence = dependentSequence.get()) < sequence) {
        barrier.checkAlert();
    }

いくつかのテストの後、この可能な解決策に出くわしました:

var availableSequence: Long = dependentSequence.get()

while(availableSequence < sequence) {
  this.lock.lock()
  this.lock.unlock()
  availableSequence = dependentSequence.get()
}

availableSequence

基本的に、1 つのスレッドがリソースをロックし、それによって他のすべてのコンシューマを一時的に保留して、CPU の高い使用率を回避します。

ここでの 2 番目のポイントは while 条件です。これは、使用可能なシーケンス (依存スレッドのシーケンス) が現在のシーケンス番号を下回っているときに発生します。これは、たとえば A が例外をスローした場合など、1 つのスレッドがロックを保持している場合にのみ発生します。

これが有効な解決策であるかどうか、または望ましくない副作用が発生する可能性があるかどうかは、まだ調査中です。

それについては大歓迎です。

于 2015-03-13T16:40:30.923 に答える