| = Master Component |
| :doctitle: Master |
| :shortname: master |
| :artifactid: camel-master |
| :description: Have only a single consumer in a cluster consuming from a given endpoint; with automatic failover if the JVM dies. |
| :since: 2.20 |
| :supportlevel: Stable |
| :tabs-sync-option: |
| :component-header: Only consumer is supported |
| |
| *Since Camel {since}* |
| |
| *{component-header}* |
| |
| The Camel-Master endpoint provides a way to ensure only a single consumer in a cluster consumes from a given endpoint; |
| with automatic fail over if that JVM dies. |
| |
| This can be handy if you need to consume from some legacy back end that either doesn't support concurrent |
| consumption or due to commercial or stability reasons, you can only have a single connection at any point in time. |
| |
| == URI format |
| |
| ---- |
| master:namespace:endpoint[?options] |
| ---- |
| |
| Where endpoint is any Camel endpoint, you want to run in master/slave mode. |
| |
| |
| // component options: START |
| include::partial$component-configure-options.adoc[] |
| include::partial$component-endpoint-options.adoc[] |
| include::partial$component-endpoint-headers.adoc[] |
| // component options: END |
| |
| == Usage |
| |
| === Starting the delegated consumer |
| |
| When a node takes the leadership, the delegated consumer is started in the background, and the start is |
| retried when it fails, for instance because the back end it consumes from is not reachable yet. The retries |
| are configured on the component with `backOffDelay` (the delay between attempts, 5000 millis by default) |
| and `backOffMaxAttempts` (the number of attempts, 10 by default). |
| |
| Once the attempts are used up, the node keeps the leadership but consumes nothing until the leadership |
| changes again, which is logged at ERROR level. Set `backOffMaxAttempts` to 0 to keep retrying for as long as |
| the node is the leader instead. |
| |
| === Using the master endpoint |
| |
| Prefix any camel endpoint with **master:someName:** where _someName_ is a logical name and is |
| used to acquire the master lock. |
| For instance: |
| |
| [tabs] |
| ==== |
| Java:: |
| + |
| [source,java] |
| ---- |
| from("master:cheese:jms:foo") |
| .to("activemq:wine"); |
| ---- |
| |
| XML:: |
| + |
| [source,xml] |
| ---- |
| <route> |
| <from uri="master:cheese:jms:foo"/> |
| <to uri="activemq:wine"/> |
| </route> |
| ---- |
| |
| YAML:: |
| + |
| [source,yaml] |
| ---- |
| - route: |
| from: |
| uri: master:cheese:jms:foo |
| steps: |
| - to: |
| uri: activemq:wine |
| ---- |
| ==== |
| |
| In this example, the master component ensures that the route is only active in one node, at any given time, in the cluster. |
| So if there are 8 nodes in the cluster, then the master component will elect one route to be the leader, and only |
| this route will be active, and hence only this route will consume messages from `jms:foo`. |
| In case this route is stopped or unexpectedly terminated, then the master component will detect this, |
| and re-elect another node to be active, which will then become active and start consuming messages from `jms:foo`. |
| |
| TIP: Apache ActiveMQ 5.x has such a feature out of the box called https://activemq.apache.org/exclusive-consumer.html[Exclusive Consumers]. |
| |
| |
| == Example |
| |
| You can protect a clustered Camel application to only consume files from one active node. |
| |
| ._Java-only: string concatenation to build the master endpoint URI_ |
| [source,java] |
| ---- |
| // the file endpoint we want to consume from |
| String url = "file:target/inbox?delete=true"; |
| |
| // use the camel master component in the clustered group named myGroup |
| // to run a master/slave mode in the following Camel url |
| from("master:myGroup:" + url) |
| .log(name + " - Received file: ${file:name}") |
| .delay(delay) |
| .log(name + " - Done file: ${file:name}") |
| .to("file:target/outbox"); |
| ---- |
| |
| The master component leverages CamelClusterService you can configure using |
| |
| * *Java* |
| + |
| ._Java-only: programmatic ZooKeeperClusterService configuration_ |
| [source,java] |
| ---- |
| ZooKeeperClusterService service = new ZooKeeperClusterService(); |
| service.setId("camel-node-1"); |
| service.setNodes("myzk:2181"); |
| service.setBasePath("/camel/cluster"); |
| |
| context.addService(service) |
| ---- |
| |
| * *Xml (Spring)* |
| + |
| [source,xml] |
| ---- |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation=" |
| http://www.springframework.org/schema/beans |
| http://www.springframework.org/schema/beans/spring-beans.xsd |
| http://camel.apache.org/schema/spring |
| http://camel.apache.org/schema/spring/camel-spring.xsd"> |
| |
| |
| <bean id="cluster" class="org.apache.camel.component.zookeeper.cluster.ZooKeeperClusterService"> |
| <property name="id" value="camel-node-1"/> |
| <property name="basePath" value="/camel/cluster"/> |
| <property name="nodes" value="myzk:2181"/> |
| </bean> |
| |
| <camelContext xmlns="http://camel.apache.org/schema/spring" autoStartup="false"> |
| ... |
| </camelContext> |
| |
| </beans> |
| ---- |
| |
| * *Camel Main / Spring Boot* |
| + |
| [source,properties] |
| ---- |
| camel.cluster.zookeeper.enabled = true |
| camel.cluster.zookeeper.id = camel-node-1 |
| camel.cluster.zookeeper.basePath = /camel/cluster |
| camel.cluster.zookeeper.nodes = myzk:2181 |
| ---- |
| |
| == Implementations |
| |
| Camel provides the following ClusterService implementations: |
| |
| - camel-consul |
| - camel-file |
| - camel-infinispan |
| - camel-jgroups-raft |
| - camel-jgroups |
| - camel-kubernetes |
| - camel-zookeeper |