One of the most common use cases while building flows/applications in mule is to be able to communicate to external systems. The performance of that external system is often beyond the user’s control. It could be possible where the rate at which mule flow sends the messages outbound is faster than the rate at which that external system could process the message. In such scenarios, there is a need to be able to perform some kind of throttling so that we don’t burden/break the external system. Again it is needless to say that the call to the external system could be synchronous or asynchronous depending on whether one cares to do some processing with the response or not. Our approach to throttling greatly depends on the exchange pattern of the outbound call to the external system.
The key here is to use the scheduler support provided by Active MQ.
Since we connect to ActiveMQ, we need to have the apache active mq library in the build path and the libraries required can be found here.
Before we go any further, please make sure that you have made the following changes to the activemq.xml file in the conf folder of your activemq installation.
Default config contains:
Change it to:
Note: Restart activemq after making the config change.
We make use of AMQ_SCHEDULED_DELAY to inject a delay before being delivered by the broker.
Now lets look at how we throttle depending on the exchange pattern of the outbound call to the external system.
Now in scenarios where one does not care about the response that is returned by the external system, it is fairly simple. We just set the AMQ_SCHEDULED_DELAY before sending the message via the jms outbound endpoint.
Let’s consider a scenario where we receive http requests and perform some transformations and send it off to an external system via a one-way endpoint. In this case, we don’t care for the response that we get back from the external system. As discussed, the goal is to inject a delay before we send the message to the external system. To simplify things a little bit we just use a logger in place of the one way outbound endpoint (that makes the call to the external system). To perform throttling we split the original flow that would have been just an http inbound endpoint followed by the one way outbound endpoint (with some message processors in the middle) into two flows: flow 1 that receives the requests via http inbound endpoint, introduces a delay using a message property followed by a jms outbound endpoint.
flow 2 that reads the message via the jms inbound end point and calls the external system(which is a logger in our example but it could really be any transport).
The complete configuration looks like:
It gets little interesting when one really cares about the response that is returned from the external system to be able to process downstream. To accomplish sychronous throttling we make use of request-reply router.
To simulate the call to the external system, we make use of VM endpoint with a request response exchange pattern. In this example we have three flows:
This flow receives requests via an http inbound endpoint, introduces a delay by setting the message property “AMQ_SCHEDULED_DELAY” and then JMS endpoints enclosed with in request-reply router.
This flow reads the message via jms inbound endpoint, and call the external system via an outbound endpoint with exchange pattern set to request-response.
This flow simulates the external system that will be called by the outbound endpoint in Flow2.
The bottomline is we are using the scheduler support provided by the JMS in stead of using some other not so clean ways like using a script to perform a thread.sleep(). This approach is lot cleaner.
Note: I’ve only evaluated this using ActiveMQ. From what I can see in documentation it should be supported by the most common platforms. Please feel free to comment if you have experience from using scheduler support with other platforms.