JGroups Overview
The JGroups Transport consists of a Connector, Receiver and Dispatcher. The protocol is "jgroups://". The group name is the URI, so "jgroups://testgroup", will mean that the receiver or dispatcher will register a JGroups Channel on the "testgroup" group.
The JGroupsMessageDispatcher is set up for both synchronous and asynchronous behaviour. Depending on the scenario, it uses different JGroups blocks. For lifecycle control, I've wrapped the blocks I'm using as JGroupsAdapter instances in the adapters subdirectory.
Listeners are in the listeners subdirectory.
Clustering Services (UMOs)
USing the JGroups transport it is possible to cluster servce invokations across machines. I have three Mule instances: one which is the entry point for the process, and two that have the UMOs that do the work. As the two worker nodes go up and down, the work still gets processed. I have built in logic to choose preferred workers and rediscover nodes when one or another goes down.
Examples
Clustered UMO Example
To test this, you need three Mule nodes: one the entry point, and the other two the workers.
The entry point configuration looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mule-configuration PUBLIC "-//MuleSource //DTD mule-configuration XML
V1.0//EN" "http://mule.mulesource.org/dtds/mule-configuration.dtd">
<mule-configuration id="Sample" version="1.0">
<mule-environment-properties synchronous="true"/>
<model name="sample">
<mule-descriptor name="testService"
implementation="org.mule.components.simple.PassThroughComponent">
<inbound-router>
<endpoint address="stream://System.in?promptMessage=Enter:"/>
</inbound-router>
<outbound-router>
<router className="org.mule.routing.outbound.OutboundPassThroughRouter">
<endpoint address="vm://out"/>
<reply-to address="stream://System.out?outputMessage=Response:"/>
</router>
</outbound-router>
</mule-descriptor>
<mule-descriptor name="testOut"
implementation="org.mule.components.simple.PassThroughComponent">
<inbound-router>
<endpoint address="vm://out"/>
</inbound-router>
<outbound-router>
<router className="org.mule.routing.outbound.OutboundPassThroughRouter">
<endpoint address="jgroups://testgroup"/>
</router>
</outbound-router>
</mule-descriptor>
</model>
</mule-configuration>
All this configuration does is to take what you type on the console and send it to the JGroups cluster, via the jgroups transport. When the response comes back, then it is routed to stdout.
The worker configuration looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mule-configuration PUBLIC "-//MuleSource //DTD mule-configuration XML
V1.0//EN" "http://mule.mulesource.org/dtds/mule-configuration.dtd">
<mule-configuration id="Sample" version="1.0">
<mule-environment-properties synchronous="true"
serverUrl="tcp://localhost:60505"/>
<model name="sample">
<mule-descriptor name="testService"
implementation="org.mule.components.UpperCaseComponent">
<inbound-router>
<endpoint address="jgroups://testgroup"/>
</inbound-router>
</mule-descriptor>
</model>
</mule-configuration>
Here, the UMO simple converts the incoming String to upper case.
To run the example, start the worker nodes on two different machines. Then start the entry point node, and type something in. If you have the line
log4j.logger.org.mule.providers.jgroups=DEBUG
in your log4.properties, then you'll see all sorts of messages about how the dispatcher picks its destinations.
Obviously we still have a point of failure on the entry point Mule instance. There is some work to be done here. One option is have a clustered JMS entry point.
Simple File Replication Example
This is not really true file replication, but it shows how a file read by one Mule node can be replicated to another. You need, obviously, two nodes, whether on the same machine or different.
The first node configuration is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mule-configuration PUBLIC "-//MuleSource //DTD mule-configuration XML
V1.0//EN" "http://mule.mulesource.org/dtds/mule-configuration.dtd">
<mule-configuration id="Sample" version="1.0">
<model name="sample">
<mule-descriptor name="testService"
implementation="org.mule.components.simple.PassThroughComponent">
<inbound-router>
<endpoint address="file://input?moveToDirectory=archive"/>
</inbound-router>
<outbound-router>
<router className="org.mule.routing.outbound.OutboundPassThroughRouter">
<endpoint address="jgroups://testgroup"/>
</router>
</outbound-router>
</mule-descriptor>
</model>
</mule-configuration>
The second node configuration is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mule-configuration PUBLIC "-//MuleSource //DTD mule-configuration XML
V1.0//EN" "http://mule.mulesource.org/dtds/mule-configuration.dtd">
<mule-configuration id="Sample" version="1.0">
<mule-environment-properties serverUrl="tcp://localhost:60505"/>
<model name="sample">
<mule-descriptor name="testService"
implementation="org.mule.components.simple.PassThroughComponent">
<inbound-router>
<endpoint address="jgroups://testgroup"/>
</inbound-router>
<outbound-router>
<router className="org.mule.routing.outbound.OutboundPassThroughRouter">
<endpoint address="file://output"/>
</router>
</outbound-router>
</mule-descriptor>
</model>
</mule-configuration>
Start the first node, and as many instance as you want of the second. As you feed in files to the first one, the others will receive them as well.