The Master component provides a failover mechanism for Apache Camel endpoints, based on
Fuse Fabric. Using the Master component, you can make almost any type of Apache Camel endpoint
participate in a failover cluster, simply by prefixing the consumer endpoints with
master:.ClusterID:
The Master component can only be used in the context of a fabric-enabled Fuse ESB Enterprise
container. You must ensure that the fabric-camel feature is installed. If
necessary, you can install it using the following console command:
karaf@root> features:install fabric-camel
Alternatively, if you decide to use a custom feature to deploy your application, you can
ensure that the fabric-camel feature is installed by including it in your
feature definition. For example:
<?xml version="1.0" encoding="UTF-8"?>
<features>
<feature name="fabric-component-example">
<feature>fabric-camel</feature>
<bundle>URIforMyBundle</bundle>
<!-- Specify any other required bundles or features -->
...
</feature>
</features>For more details about features, see Deploying Features in Deploying into the Container.
A Master endpoint can only be used as a consumer endpoint. It has the following URI format:
master:ClusterID:PublishedURI[?Options]
Where the URI, , is published in the
fabric registry and associated with the PublishedURI
cluster.ClusterId
The Master component itself does not support any URI options. It is possible, however, to specify options for the published URI. These options are stored in the fabric registry as part of the URI and are used as follows:
Server-only options—options that are applicable only to the server are applied to the server endpoint (consumer endpoint) at run time.
Client-only options—options that are applicable only to the client are applied to the client endpoint (producer endpoint) at run time.
Common options—options common to the client and the server are applied to both.
Figure 3 gives an overview of how Master endpoints enable you to create a failover cluster.
The sample failover cluster consists of two servers, with the URIs,
master:FD:jetty:http://0.0.0.0:9090 and
master:FD:jetty:http://0.0.0.0:9191. When the servers are created, they
compete to grab a lock on the FD entry in the fabric registry. Whichever
server manages to get the lock (in this example, the server listening on port
9090) becomes the master, registering its URI under the cluster ID,
FD, and activating its route. The other servers remain slaves: they are not
able to register their URIs under the FD cluster ID, their routes do
not get activated, and they continue to try the lock on the
FD registry entry, in case the master server should fail.
The client must be defined using a Fabric endpoint (see Fabric). In this example, when the client route starts, it looks up the ID,
FD, to find the master's endpoint URI, and then connects to the master
server.
At some point, the master server could fail. When this happens, the following sequence of events occurs:
Now that the master has died, the lock is free again. One of the slaves will succeed in grabbing the lock and become the new master.
The new master registers its URI under the
FDcluster ID, replacing the URI of the old master.The auto-reconnect capability of the Fabric endpoint in the client is activated. The client detects that the master has died, goes back to the fabric registry to obtain the URI of the new master, and then connects to the new master.
To create a failover cluster, all that you have to do is to publish more than one endpoint URI under the same cluster ID, using Master endpoints. Now, when a client looks up that cluster ID, it gets the URI of the currently active server in the cluster (the master). If the original server should fail, the client will automatically go back to the fabric registry to get the URI of the new master and then connect to the new master.
The servers in the failover cluster have almost the same configuration. Essentially, the only difference between them is that they publish an endpoint URI with a different hostname and/or IP port. Instead of creating a separate OSGi bundle for every single server in the failover cluster, however, it is better to define a template that enables you to specify the host or port using a configuration variable.
Example 6 illustrates the template approach to defining servers in a failover cluster, highlighting the relevant parts of the code.
Example 6. Server Template for a Failover Cluster
<?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"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<!-- osgi blueprint property placeholder -->
<cm:property-placeholder id="placeholder" persistent-id="masterCamel">
<cm:default-properties>
<cm:property name="portNumber" value="8181"/>
</cm:default-properties>
</cm:property-placeholder>
<reference id="org.linkedin.zookeeper.client.IZKClient"
interface="org.linkedin.zookeeper.client.IZKClient" />
<camelContext id="camel" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route id="failover-server">
<from uri="master:FailoverDemo:jetty:http://0.0.0.0:{{portNumber}}/master"/>
<log message="Request received : ${body}"/>
<setHeader headerName="karaf.name">
<simple>${sys.karaf.name}</simple>
</setHeader>
<transform>
<simple>Response from Zookeeper agent</simple>
</transform>
</route>
</camelContext>
</blueprint>A reference to the org.linkedin.zookeeper.client.IZKClient OSGi service is
created using the reference element. This reference is needed, because the
Master component implicitly looks for an IZKClient object in the bean registry
and uses this object to connect to the underlying fabric.
The route starts with a from command that specifies a Master endpoint URI.
The Master endpoint registers the given Jetty URI under the FailoverDemo
cluster ID, which effectively means that the server joins the FailoverDemo
failover cluster.
This example also illustrates how to use the OSGi blueprint property placehoder. The
property placehoder mechanism enables you to read property settings from the OSGi Config
Admin service and substitute the properties in the blueprint configuration file. In this
example, the property placeholder accesses properties from the masterCamel
persistent ID. A persistent ID in the OSGi Config Admin service identifies a collection of
related property settings. After initializing the property placeholder, you can access any
property values from the masterCamel persistent ID using the syntax,
{{.PropName}}
The Master endpont URI exploits the property placeholder mechanism to substitute the
value of the Jetty port, {{portNumber}}, at run time. At deploy time, you can
specify the value of the portName property. For example, if using a custom
feature, you could specify the property in the feature definition (see Add OSGi
configurations to the feature in Deploying into the Container). Alternatively, you can specify configuration
properties when defining deployment profiles in the Fuse Management
Console.
To look up a URI in the fabric registry, simply specify the fabric endpoint URI with an
ID, in the format, fabric:. This syntax is
used in a producer endpoint (for example, an endpoint that appears in a ClusterIDto DSL
command).
Example 7 shows a route that implements a HTTP client, where the
HTTP endpoint is discovered dynamically at run time, by looking up the specified ID,
FailoverDemo, in the fabric registry.
Example 7. Looking up a URI
<?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"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<reference id="org.linkedin.zookeeper.client.IZKClient"
interface="org.linkedin.zookeeper.client.IZKClient"/>
<camelContext id="camel" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route id="failover-client">
<from uri="timer://foo?fixedRate=true&period=10000"/>
<setBody>
<simple>Hello from Zookeeper server</simple>
</setBody>
<to uri="fabric:FailoverDemo"/>
<log message=">>> ${body} : ${header.karaf.name}"/>
</route>
</camelContext>
</blueprint>The client route also needs a reference to the
org.linkedin.zookeeper.client.IZKClient OSGi service, which the Fabric
component uses to connect to the underlying fabric.
Because the route is implemented in blueprint XML, you would normally add the file
containing this code to the src/main/resources/OSGI-INF/blueprint directory of
a Maven project.
When defining an OSGi bundle that uses Master endpoints, the Import-Package
bundle header must be configured to import the following Java packages:
org.fusesource.fabric.zookeeper.spring org.linkedin.zookeeper.client
For example, assuming that you use Maven to build your application, Example 8 shows how you can configure the Maven bundle plug-in to import the required packages.
Example 8. 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>
org.fusesource.fabric.zookeeper.spring,
org.linkedin.zookeeper.client,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
...
</project>







