Design Notes for ThreadPool Configuration
CAMEL-1588 is the ticket for a new and improved thread pool configuration for Apache Camel. Its intended for Camel 2.3.
Scope
Camel uses thread pool in various places such as EIP patterns, Components, Async API and whatnot. The aim is to improved and allow easier to configure those thread pools in a more streamlined manner. The goal is to offer both a fine grained configuration where you can tweak individual pools and have more coarse grained configuration with fallback to global settings etc.
Outside scope
Some components provides their own thread pool configuration and management which Camel of course cannot and should not try to tailor with. For example Jetty is such an example.
Usages of thread pools in Camel
Currently Camel uses thread pools in camel-core in the following areas:
DefaultComponent
- Optional thread pool for components in need of suchDefaultEndpoint
- Optional thread pool for endpoints in need of suchDefaultProducerTemplate
- Used by the Async API of this templateScheduledPollConsumer
- Needs aScheduledExecutorService
to schedule its tasksRecipientListDefinition
- The Recipient List EIP patternSplitDefinition
- The Splitter EIP patternThreadsDefinition
- Thethreads
DSLToDefinition
- Used by thetoAsync
variationWireTapDefinition
- The Wire Tap EIP patternMulticastProcessor
- The underlying thread poolOnCompletionProcessor
- For sending async on completion routesSendAsyncProcessor
- ThetoAsync
processor variationThreadsProcessor
- The underlying thread poolWireTapProcessor
- For sending async wire tapsSedaConsumer
- To support theconcurrentConsumers
andmultipleConsumers
options (uses separate pools)
Existing configuration
You can configure the thread pool using the setExecutorService setter methods that usually exists on those places where its in use. Some EIP patterns offer a executorServiceRef
option to refer to some pool to be looked up in the Registry.
We should ensure all EIPs can be configured to use a custom thread pool in a nice and easy way. DONE
Using default ThreadPools
We should use CachedThreadPool
from the JDK Core as its the best general purpose pool for many short lived tasks, which is what Camel really does. Processing many messages in a short live. DONE
Only used SingleExecutorService for background tasks, and ScheduledExecutorService for scheduled tasks DONE
ThreadPool scope
It should be possible to configure a thread pool on either per CamelContext level or per Route level, such as you can do with AutoStartup and the likes.
Then you can say, eg this route should use this pool, which have 20/50 in the pool size etc. CHANGE OF PLAN
Thread pool configuration by rules
It should be possible to to define a set of rules which matches which thread pool a given source should use.
It should be pattern based so you can say all EIPs should use this pool, all endpoints that pool etc.
A ruleset something like this:
<threadPoolRule route="*" source="Aggregator" executorServiceRef="myAggPool"/> <threadPoolRule route="*" source="To" executorServiceRef="mySendPool"/> <threadPoolRule route="route3" source="*" executorServiceRef="myRoute3Pool"/>
Where it will match against route first, so if we got a route3 then it will pick among those
It should be possible to use wildcard and reg exp in the route
and source
attributes.
The problem with shutdown and restarting pools
The ExecutorService API does not allow to restart a thread pool, which is PITA. So we need to find a better strategy for stopping vs. shutdown.
Currently when we stop we also terminate the threadpool, and then re-create it on start. This only works for default pools which we can create again.
But for custom thread pools we have no way to create them again as the pool is already created when its given to us.
We may have to only shutdown thread pools if CamelContext is stopping. And then if end user stop a route from JMX we can keep the thread pool around.
Only issue is the scheduled pool should stop scheduling tasks, which may be a bit more trickier to avoid.
The problem with Component, Endpoint
The DefaultComponent and DefaultEndpoint exposes API to get an ExecutorService. We should remove these API as you should use ExecutorServiceStrategy
from CamelContext
to obtain a thread pool. DONE
Managed thread pool
Check whether the thread pools is managed by default and avail in JConsole. If not we should probably at least expose some read-only data about the pools.
Spring Factory for creating custom pools
Create a Spring XML DSL for defining thread pools using custom options such as corePoolSize, maxPoolSize, keepAlive, thread name etc. DONE
Pluggable ExecutorService SPI
We need a org.apache.camel.spi.ExeuctorServieStrategy
which is pluggable so end users can plugin their own strategy how to create thread pools. They can leverage a WorkManager API from J2EE server etc. DONE
Customizable thread name
We should offer a simple pattern syntax so end users can customize the pattern the thread name is created with: eg Something like: Camel Thread ${counter} - ${name
}. Where counter and suffix is dynamic parameters. The counter is an unique incrementing thread counter. And name is provided from the source which as a way to name thread, such as a seda endpoint uri. DONE