Most modern, distributed applications require some form of coordination service to ensure tasks or jobs run only where they’re supposed to. For example, it may be necessary to run a cleanup task on dedicated servers. Writing your own master election or coordination service can be difficult. This is where Apache ZooKeeper comes in. ZooKeeper provides “centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.”
Unfortunately, ZooKeeper isn’t the easiest collection of services to just drop into your application. The learning curve can be fairly steep. This is where another Apache project comes in: Camel. Camel provides a ZooKeeper component and some supporting classes to take advantage of ZooKeeper’s more powerful features. The feature I’m most interested in is master election.
Camel’s ZooKeeper component supports master election using a standard route policy. The ZooKeeperRoutePolicy monitors a common znode on the ZooKeeper ensemble. For example:
ZooKeeperRoutePolicy routePolicy = new ZooKeeperRoutePolicy("zookeeper://10.211.55.4:2181/status/reportgen", 1);
This route policy allows one client to bind to the “/status/reportgen” znode. If I wanted three clients to be able to bind to the znode, I would simply change the number in the route policy to 3. Once the route policy is defined, it is plugged into the route:
from("quartz://cluster/heartbeat?cron=0/30+*+*+*+*+?") .routePolicy(routePolicy) .to("mock:generate-reports");
The above Camel route executes every 30 seconds. The “mock:generate-reports” is only executed on the client able to bind to the relevant znode.
Before I discovered Camel’s ZooKeeper component, I tried several options for distributed master election, including ActiveMQ’s exclusive consumer and rolling my own master election process. From my experience, ZooKeeper offers the easiest out of the box solution for a distributed environment.
In the future, I’ll explore some of the additional challenges I faced implementing Camel’s ZooKeeper component. If you’re using ZooKeeper, let me know in the comments.