2016-06-16 13 views
2

私はApache Camel 2.15を使用しています。 REST API呼び出しで受信したデータを直接エンドポイントであるCamelルートに配置します。このルートは、分割されたEIPを使用し、直接のエンドポイントでもある別のCamelルートを呼び出します。ここでCamel Split EIPとプール内のスレッドの使用がminスレッドを超えていないようです

は、関連するキャメルコードが

from("direct:activationInputChannel").routeId("cbr_activation_route") 
// removed some processes 
.split(simple("${body}")) 
    .parallelProcessing() 
    .to("direct:activationItemEndPoint") 
.end() 
// removed some processes 

from("direct:activationItemEndPoint").routeId("cbr_activation_item_route") 
.process(exchange -> this.doSomething(exchange)) 
// removed some processes 

呼び出しは同期で、同じスレッドで実行するようになります直接エンドポイントを使用するように見えるものです。 Split/parallelProcessingを使用すると、2番目のルートが別のスレッドで実行されます。スプリッタはデフォルトのスレッドプールを使用しています。

jMeterを使用してアプリケーションに対していくつかの負荷テストを実行したとき、スプリットルートがボトルネックになっていました。 200スレッドを使用した負荷テストでは、Tomcat HTTPスレッドプールがjConsoleにcurrentThreadCountという200の値を持つことがわかりました。私はまた、キャメルルートcbr_activation_routeが200 ExchangesInflightを持っていたことを観察した。

enter image description here

問題はcbr_activation_item_routeはわずか50 ExchangesInflightを有していました。番号50は、デフォルトプールに設定されているpoolSizeに対応しています。 maxPoolSizeは500に設定され、maxQueueSizeは1000(デフォルト)に設定されました。

このルートの機内交換の回数は、最小プールサイズを上回ることはありません。たくさんのリクエストがキューに入れられ、スレッドが利用可能であったにもかかわらず。 CamelのデフォルトスレッドプールのpoolSizeを200に変更したとき、cbr_activation_item_routeは新しい最小値を使用し、200 ExchangesInflightでした。利用可能なスレッドがさらに多くても負荷がかかっていても、Camelは最小値より多くのスレッドを使用しないようです。

この現象の原因となっている設定や何かがありますか?最小値が50に設定されているときにCamelが最初のテスト実行で200スレッドを使用しないのはなぜですか?

ありがとうございました

+0

「このルートの機内交換の回数が最小プールサイズを超える上昇したことはありません。」私はpoolSizeを200に変更すると、cbr_activation_item_routeには200個のExchangesInflightがありました。 "私にとって何が問題なのかははっきりしていません。 – javamonkey79

+0

最初のテストではCamelプールが50分と500最大スレッドに設定されていました。キャメルが最初のルート(内線交換)で200のアクティブなリクエストを受け取ったとき、スプリットは50分しか使用しませんでした。パフォーマンスがそれほど高くなかったので、スレッド数を増やす必要があったようです。私は分を200に上げ、分割は200回の機内交換を持つことができました。最大500を与えられた私はキャメルがここでもっと多くのスレッドを使うようにするためにminを上げなければならないとは思わなかった。 –

+0

は、上記の質問でこれを明確にしました(うまくいけば)。ありがとうございます。 –

答えて

1

これは正常な動作です。これはCamel自体とは関係ありませんが、一般的にはJavaのThreadPoolExecutorです。

リンクされたドキュメントを読めば、そこにそれは言う:

corePoolSizeよりますがmaximumPoolSizeスレッドが実行されているよりも少ないがある場合は、新しいスレッドはキューがいっぱいになった場合にのみ作成されます。

あなたが1000にmaxQueueSizeを設定する場合は、新しいスレッドが作成される前に、1050件のリクエストを作成する必要があり、200しようとするまで、あなたの要求をキューに登録したくない場合はSynchronousQueueを使用するようにキャメルを伝える(推奨されません、 私見では)。

+0

私は 'ThreadPoolExecutor 'を読んできましたが、これは意図された動作です。 –

+0

を除いて、多くの私たちの低パフォーマンス - 私たちはスプリットEIPがより多くのスレッドにアクセスしていないと考えていた - は、HTTP4コンポーネントのデフォルト設定でした。デフォルトの 'connectionsPerRoute'が20で、スプリットルートから別のRESTサービスを呼び出していたことがわかります。この値を上げると、大いに役立ちます。 :) –

3

Javaのスレッドプールエグゼキュータの動作に関するFredericoの答えに同意します。 'corePoolSize'スレッドに達した後で、より多くのスレッドを作成するのではなく、キューに新しい要求を追加することを好みます。

'corePoolSize'に達した後にTPEにリクエストが来るようにするには、JavaがBlockingQueueのoffer()メソッドをキューに入れてキューに入れているという事実に基づいて、要求。 offer()メソッドがfalseを返すと、新しいスレッドが作成され、ExecutorのrejectedExecutionHandlerが呼び出されます。 offer()メソッドをオーバーライドし、独自のバージョンのThreadPoolエグゼキュータを作成して、負荷に基づいてスレッド数を調整できます。

私はここで、この例が見つかりました:https://github.com/kimchy/kimchy.github.com/blob/master/_posts/2008-11-23-juc-executorservice-gotcha.textile

関連する問題