The Problem
When managing events, it's common to encounter a rapid succession of events within a brief period. For instance, within an application driven by events, creating an entity can trigger multiple events like EntityAdded, EntityChanged, SubEntityAdded, etc. However, if the primary objective is to monitor changes in a specific entity item, processing all these events to dispatch a notification or outbound message to downstream systems might be unnecessary.
The Solution
Based on the problem described above, we are often interested in only knowing that an update has occurred at a certain moment, rather than communicating every single change. This can be effectively managed within a short predefined timeframe, typically 5 to 10 seconds.
This pattern is particularly common when dealing with primary business objects. While each change can generate multiple events, downstream systems don’t need to process all updates individually, they only need to know that an object was modified and should fetch the latest state.
The goal is to inform interested parties that an update has occurred while avoiding unnecessary system load, especially to external systems. One approach is to implement a throttling mechanism leveraging Apache Camel components.
Apache Camel's Master component provides an elegant solution for implementing this throttling mechanism, especially in clustered environments. The Master component ensures that only one node in a cluster actively consumes from an endpoint, preventing duplicate processing when multiple application instances are running. However, the Master component alone is not sufficient and it requires a transport mechanism that supports distributed messaging. This is where message queue services like Amazon SQS, JMS-compliant brokers (such as ActiveMQ), or other similar messaging platforms or distributed cache systems become essential to enable proper coordination across the cluster.
Why SQS Over Direct Component?
While it might be logical to use Camel's direct component for internal routing, this approach has significant limitations in clustered environments. This component only works within a single JVM, making it unsuitable for distributed deployments. When using direct with the Master component, only the elected leader route will work properly while the other routes in other nodes will fail when attempting to consume messages from that endpoint, as the direct endpoint simply doesn't exist in their JVM context.
Using Amazon SQS solves this problem by providing a centralized message store where all cluster nodes can access the same message queue.
Implementation Pattern
Here is how to implement throttling with the Master component and SQS:
from("master:notification:aws2-sqs://queue-1")
.routeId(“throttlingRoute”)
.aggregate().exchangeProperty(ENTITY_ID_PROPERTY)
.completionTimeout(“5000”)
.aggregationStrategy(new UseLatestAggregationStrategy())
.to(“direct:notify”);
This works as follows:
- Multiple messages are sent to the SQS queue.
- Those messages arrive at the SQS queue in an interval of a few seconds.
- The Master component ensures only the elected leader route consumes the messages.
- The aggregation strategy discards all but the latest message.
- After the completion timeout is reached, only the latest message proceeds to the notification process.
- If the leader route fails, another route in another node is automatically elected and continues processing.
The pattern described above is particularly valuable for status update handlers and any scenario where notifying about one state among various that occurred at almost the same time, or the most recent state, is more important than notifying every intermediate change.

Top comments (0)