Camel Split EIP 和池中线程的使用似乎没有超过最小线程
Camel Split EIP and use of threads in pool doesn't seem to go over min threads
我正在使用 Apache Camel 2.15 并发现了一个有趣的行为。
我将通过 REST API 调用接收到的数据放入作为直接端点的 Camel 路由中。该路由又使用拆分的 EIP 并调用另一个也是直接端点的 Camel 路由。
这是相关的 Camel 代码的样子
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 用法导致第二条路由到 运行 在单独的线程上。拆分器使用默认线程池。
当我 运行 使用 jMeter 对应用程序进行一些负载测试时,我发现拆分路由正在成为瓶颈。通过使用 200 个线程的负载测试,我观察到 Tomcat http 线程池在 jConsole 中的 currentThreadCount
为 200。我还观察到 Camel 路线 cbr_activation_route
有 200 ExchangesInflight
。
问题是 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 个线程 运行?
谢谢
这是预期的行为。这与 Camel 本身无关,但通常与 Java 的 ThreadPoolExecutor
有关。
如果您阅读链接文档,会发现:
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
如果您将 maxQueueSize
设置为 1000,则必须在创建新线程之前创建 1050 个请求,最多 200 个。如果您不想要您的线程,请尝试告诉 Camel 使用 SynchronousQueue
请求排队(不推荐,恕我直言)。
同意 Frederico 关于 Java 线程池执行器行为的回答。它更愿意向队列中添加新请求,而不是在达到 'corePoolSize' 个线程后创建更多线程。
如果您希望您的 TPE 在达到 'corePoolSize' 之后随着请求的到来添加更多线程,那么根据 Java 调用报价这一事实,有一种稍微复杂的方法可以实现这一点BlockingQueue 中的 () 方法对请求进行排队。如果 offer() 方法 returns false,它会创建一个新线程并调用 Executor 的 rejectedExecutionHandler。可以覆盖 offer() 方法并创建您自己的 ThreadPool 执行器版本,它可以根据负载缩放线程数。
我在这里找到了一个例子:https://github.com/kimchy/kimchy.github.com/blob/master/_posts/2008-11-23-juc-executorservice-gotcha.textile
我正在使用 Apache Camel 2.15 并发现了一个有趣的行为。 我将通过 REST API 调用接收到的数据放入作为直接端点的 Camel 路由中。该路由又使用拆分的 EIP 并调用另一个也是直接端点的 Camel 路由。
这是相关的 Camel 代码的样子
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 用法导致第二条路由到 运行 在单独的线程上。拆分器使用默认线程池。
当我 运行 使用 jMeter 对应用程序进行一些负载测试时,我发现拆分路由正在成为瓶颈。通过使用 200 个线程的负载测试,我观察到 Tomcat http 线程池在 jConsole 中的 currentThreadCount
为 200。我还观察到 Camel 路线 cbr_activation_route
有 200 ExchangesInflight
。
问题是 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 个线程 运行?
谢谢
这是预期的行为。这与 Camel 本身无关,但通常与 Java 的 ThreadPoolExecutor
有关。
如果您阅读链接文档,会发现:
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
如果您将 maxQueueSize
设置为 1000,则必须在创建新线程之前创建 1050 个请求,最多 200 个。如果您不想要您的线程,请尝试告诉 Camel 使用 SynchronousQueue
请求排队(不推荐,恕我直言)。
同意 Frederico 关于 Java 线程池执行器行为的回答。它更愿意向队列中添加新请求,而不是在达到 'corePoolSize' 个线程后创建更多线程。
如果您希望您的 TPE 在达到 'corePoolSize' 之后随着请求的到来添加更多线程,那么根据 Java 调用报价这一事实,有一种稍微复杂的方法可以实现这一点BlockingQueue 中的 () 方法对请求进行排队。如果 offer() 方法 returns false,它会创建一个新线程并调用 Executor 的 rejectedExecutionHandler。可以覆盖 offer() 方法并创建您自己的 ThreadPool 执行器版本,它可以根据负载缩放线程数。
我在这里找到了一个例子:https://github.com/kimchy/kimchy.github.com/blob/master/_posts/2008-11-23-juc-executorservice-gotcha.textile