
Throttler – restricting the number of messages flowing to an endpoint
When you need to limit the number of messages flowing through a route during a specified time period, the Throttler EIP can help. For example, if you have a downstream system that can only handle 10 requests per second, using a Throttler EIP within your route can ensure that you do not exceed that rate.
This recipe will show you how to restrict the number of messages routed to a set of endpoints during a specified time period.
Getting ready
The Java code for this recipe is located in the org.camelcookbook.routing.throttler
package. The Spring XML files are located under src/main/resources/META-INF/spring
and prefixed with throttler
.
How to do it...
In order to use the Throttler, perform the following steps:
- You must specify the maximum number of messages to be allowed per time period (defaults to 1,000 ms).
In the XML DSL, this is specified as an Expression to allow for the maximum rate to be changed at runtime. In this example, we are using the Constant Expression Language to set the maximum number of messages to
5
.<route> <from uri="direct:start"/> <throttle> <constant>5</constant> <to uri="mock:throttled"/> </throttle> </route>
In the Java DSL, you can provide either
java.lang.Long
, which will be interpreted like the results of a Constant Expression Language expression, or you can provide an Expression that will be evaluated for each message to determine the current maximum number of messages per time period.from("direct:start") .throttle(5) .to("mock:throttled") .end() .to("mock:after");
- Optionally, explicitly specify the time period over which throttling is performed in your route. This is the time period for which the Throttler will only allow the maximum number of messages you specified in the previous step. This example sets the time period to 2,000 ms or 2 seconds, so every 2 seconds the Throttler will allow up to 5 messages to be processed.
In the XML DSL, this is written as:
<route> <from uri="direct:start"/> <throttle timePeriodMillis="2000"> <constant>5</constant> <to uri="mock:throttled"/> </throttle> </route>
In the Java DSL, the same route is expressed as:
from("direct:start") .throttle(5).timePeriodMillis(2000) .to("mock:throttled") .end() .to("mock:after");
How it works...
The Throttler evaluates the maximumRequestsPerPeriod
Expression for each message being processed. The processing of this message is delayed if it exceeds the specified rate. The use of an Expression allows for the throttling rate to be changed at runtime through aspects of the current message, or calls to an external Java object (using the Bean Expression Language). By default, the Throttler will block the route's thread of execution until the throttle rate drops below the specified maximum.
An example of using a message header, ThrottleRate
, to set the throttle rate is as follows. In this example, the header name can be anything, you just need to provide the name of the header whose value will be evaluated as java.lang.Long
and used as the maximumRequestsPerPeriod
.
<throttle timePeriodMillis="10000"> <header>ThrottleRate</header> <to uri="mock:throttled"/> </throttle>
There's more...
The Throttler provides an asyncDelayed
option that will take messages that would exceed the throttle rate, and schedule future execution for them, releasing the route's current thread for other uses. An alternative thread pool can be provided through the executorServiceRef
option. Here's an example in the XML DSL:
<camelContext xmlns="http://camel.apache.org/schema/spring"> <threadPoolProfile id="myThrottler" poolSize="5" maxPoolSize="20" maxQueueSize="1000" rejectedPolicy="CallerRuns"/> <route> <from uri="direct:start"/> <to uri="mock:unthrottled"/> <throttle timePeriodMillis="10000" asyncDelayed="true" executorServiceRef="myThrottler"> <constant>5</constant> <to uri="mock:throttled"/> </throttle> <to uri="mock:after"/> </route> </camelContext>
If your needs are less exacting, you can use org.apache.camel.impl.ThrottlingInflightRoutePolicy
class instead of the Throttler. The ThrottlingInflightRoutePolicy
is less accurate than the Throttler, but can be more easily applied to one or more routes within a Camel context.
See also
- Throttler: http://camel.apache.org/throttler.html
- Expression: http://camel.apache.org/expression.html
ThrottlingInflightRoutePolicy
: http://camel.apache.org/routepolicy.html#RoutePolicy-ThrottlingInflightRoutePolicy