The Master component provides a way to ensure that only a single consumer in a cluster consumes from a given endpoint; with automatic failover if that JVM dies. This feature can be useful if you need to consume from a legacy back-end that doesn't support concurrent consumption or, due to commercial or stability reasons, you can have only a single connection to the back-end at any point in time.
The Master component can only be used in the context of a fabric-enabled Red Hat JBoss
Fuse container. You must ensure that the fabric-camel feature is
installed.
In the context of Fabric, you install a feature by adding it to the relevant profile.
For example, if you are using a profile called my-master-profile, you would
add the fabric-camel feature by entering the following console
command:
karaf@root> fabric:profile-edit --features fabric-camel my-master-profile
A Master endpoint can only be used as a consumer endpoint. It has the following URI format:
master:ClusterID:EndpointURI[?Options]
Where the URI, , is published in the
fabric registry and associated with the
EndpointURI cluster.ClusterId
The Master component itself does not support any URI options. Any
options on the URI are, therefore, applied to the specified consumer endpoint,
.EndpointURI
The Master component is useful in cases where you need to poll messages from an endpoint, but you are only allowed to make one connection to that endpoint. In this case, you can use the Master component to define a failover cluster of consumer endpoints. Each Master endpoint in the cluster is capable of consuming messages from the given endpoint, but only one of the Master endpoints is active at any time (the master), while the other Master endpoints are waiting (the slaves).
For example, to set up a cluster of Master endpoints that can consume from the
seda:bar endpoint, you would proceed as follows:
Define the Master endpoints with the following URI (where each endpoint in the cluster uses exactly the same URI):
master:mysedalock:seda:bar
Each of the Master endpoints in the cluster tries to get the
mysedalock lock (implemented as a key in the Zookeeper
registry). The Master endpoint that succeeds in getting the lock becomes active
(the master) and starts consuming messages from the seda:bar
endpoint. The other Master endpoints enter a waiting state and continue to try
the lock (the slaves).
You must remember to include the fabric-camel feature in the
profile that deploys a Master endpoint.
In the Blueprint XML file that defines a Master endpoint, you must define a reference to the Apache Curator service (the Master component uses this service to connect to the Zookeeper registry). For example, in Blueprint XML you can define the Curator reference as follows:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
<reference id="curator" interface="org.apache.curator.framework.CuratorFramework"/>
...
</blueprint>In Blueprint XML, you can define a Master endpoint at the start of a Camel route, as follows:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
<camelContext id="camel" xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="master:mysedalock:seda:bar"/>
...
</route>
</camelContext>
...
</blueprint>For example, a typical way to use the Master component is to create a cluster of
exclusive consumers for consuming messages from a JMS queue. Only one of the Master
endpoints consumes from the queue at any time, and if that Master endpoint goes down,
one of the other Master endpoints takes over (becomes the new master). In this example,
we create a cluster of two Camel routes, where each route starts with a Master endpoint
that is capable of consuming from the specified queue, FABRIC.DEMO.
To create a master-slave cluster that polls messages from an ActiveMQ broker, based on the Master component, perform the following steps:
If you do not already have a fabric, enter the following console command to create one:
JBossFuse:karaf@root> fabric:create --new-userAdminUser--new-user-passwordAdminPass--zookeeper-passwordZooPass--wait-for-provisioning
The --new-user and --new-user-password options
specify the credentials for a new administrator user. The Zookeeper password is
used to protect sensitive data in the Fabric registry service (all of the nodes
under /fabric).
![]() | Note |
|---|---|
If you use a VPN (virtual private network) on your local machine, it is advisable to log off VPN before you create the fabric and to stay logged off while you are using the local container. A local Fabric Server is permanently associated with a fixed IP address or hostname. If VPN is enabled when you create the fabric, the underlying Java runtime is liable to detect and use the VPN hostname instead of your permanent local hostname. This can also be an issue with multi-homed machines. To be absolutely sure about the hostname, you could specify the IP address explicitly—see ????. |
For this example, you must have access to a running instance of an Apache ActiveMQ broker and you must know the IP port of the broker's OpenWire connector. For example, you might get access to an ActiveMQ broker in one of the following ways:
You just created the fabric on a clean installation of JBoss Fuse
(after a cold restart). In this case, the root container
ought to include the jboss-fuse-full profile by default.
You can check whether this is the case by entering the
fabric:container-list console command, as
follows:
JBossFuse:karaf@root> fabric:container-list [id] [version] [connected] [profiles] [provision status] root* 1.0 true fabric, fabric-ensemble-0000-1, jboss-fuse-full success
By default, the jboss-fuse-full profile instantiates an
ActiveMQ broker that listens on port 61616. You can use
this broker for the current example.
If no broker is running in the root container (or any other
container), you can quickly install a broker into a new fabric child
container, broker1, by entering the following fabric
command at the console prompt:
JBossFuse:karaf@root> fabric:container-create-child --profile mq-default root broker1
In this case, you can use the browser-based Fuse Management Console to discover the IP port of the OpenWire connector on the broker.
Create the master-example profile, which will be used to deploy a
simple Apache Camel route that uses the Master component. Enter the following
console command to create the profile:
JBossFuse:karaf@root> fabric:profile-create --parents default master-example
Add the requisite Karaf features to the master-example profile.
Enter the following console
commands:
fabric:profile-edit --features fabric-camel master-example fabric:profile-edit --features activemq-camel master-example
Define the simple Camel route as a resource in the master-example
profile. Invoke the built-in text editor to create a new camel.xml
resource, as follows:
fabric:profile-edit --resource camel.xml master-example
Copy and paste the following content into the built-in text editor:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<reference id="curator" interface="org.apache.curator.framework.CuratorFramework"/>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/blueprint">
<route id="fabric-server">
<from uri="master:lockhandle:activemq:queue:FABRIC.DEMO"/>
<log message="Message received : ${body}"/>
</route>
</camelContext>
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:OpenWirePort"/>
<property name="userName" value="UserName"/>
<property name="password" value="Password"/>
</bean>
</blueprint>Remember to customize the route configuration by replacing
OpenWirePort with the port number of the OpenWire
connector on the broker, and by replacing UserName
and Password by any valid JAAS credentials on the
container (for example, you could substitute the
AdminUser and
AdminPass credentials created in Step 1 of these
instructions).
To save and exit from the text editor, type Ctrl-S, Ctrl-X.
Configure the master-example profile to deploy the
camel.xml resource as an OSGi bundle. Enter the following
console command to create a new entry in the master-example agent
properties:
fabric:profile-edit --bundles blueprint:profile:camel.xml master-example
![]() | Note |
|---|---|
The |
Create two new child containers, so that you can deploy the
master-example profile as a cluster (one master and one slave).
Enter the following console command:
fabric:container-create-child root child 2
Now deploy both the master-example profile and the
mq-client profile to each of the child containers, as
follows:
fabric:container-change-profile child1 master-example mq-client fabric:container-change-profile child2 master-example mq-client
If you now send some messages to the FABRIC.DEMO queue on the
broker, the messages are consumed by one (and only one) of the deployed master
endpoints. For example, you can easily create and send messages to the broker
using the browser-based Fuse Management console.
If you stop the container that hosts the current master (initially, the
child1 container), the slave will be promoted to be the new
master (in the child2 container) and will start consuming messages
from the FABRIC.DEMO queue. For example, assuming that
child2 contains the current master, you can stop it by entering
the following console command:
fabric:container-stop child2
When defining an OSGi bundle that uses Master endpoints, the Import-Package
bundle header must be configured to import the following Java packages:
io.fabric8.zookeeper.spring io.fabric8.zookeeper
For example, assuming that you use Maven to build your application, Example 7, “Maven Bundle Plug-In Configuration” shows how you can configure the Maven bundle plug-in to import the required packages.
Example 7. Maven Bundle Plug-In Configuration
<project ... >
...
<build>
<defaultGoal>install</defaultGoal>
<plugins>
...
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Import-Package>
io.fabric8.zookeeper.spring,
io.fabric8.zookeeper,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
...
</project>