If no --> skip this article.
Have you ever had the need to send messages around the cluster, without resorting to RpcManager offered by Infinispan or HAPartition provided by WildFly ?
If no --> skip this article.
Have you ever wanted to hijack the JGroups channel used by Infinispan and WildFly and use it for your own purposes ?
If no --> skip this article.
I recently added light-weight channels [1] to JGroups. They provide the ability to send and receive messages over an existing channel, yet those messages are private to the light-weight channel. And the hijacked channel doesn't see those private messages either.
This is good when an application wants to reuse an existing channel, and doesn't want to create/configure/maintain its own channel, which would increase resource consumption.
Also, applications can create many (hundreds) of light-weight channels, as they don't use a lot of resources and are easy and quick to create and destroy.
Even better: if an application would like to add capabilities to an existing stack, e.g. atomic counters, a distributed execution service or distributed locking, then it can define the protocol(s) it wants to add and the private channel will add these. Again, the hijacked channel is unaffected by this.
There's documentation on this at [1], so let me show you how to hijack a channel inside of an Infinispan application. The application can be downloaded from [3].
The (original but edited) code that creates an Infinispan cache looks like this:
protected void start() throws Exception {
mgr=new DefaultCacheManager("infinispan.xml");
cache=mgr.getCache("clusteredCache");
eventLoop();
}
It creates a CacheManager, then creates a Cache instance off of it. This is it. Now, we want to grab the JGroups channel and hijack it to run a Draw instance on it (HijackTest:53, [4]):
protected void start() throws Exception {
mgr=new DefaultCacheManager("infinispan.xml");
cache=mgr.getCache("clusteredCache");
Transport tp;
ForkChannel fork_ch;
tp=cache.getAdvancedCache().getRpcManager().getTransport();
Channel main_ch=((JGroupsTransport)transport).getChannel();
fork_ch=new ForkChannel(main_ch,
"hijack-stack",
"lead-hijacker",
true,
ProtocolStack.ABOVE,
FRAG2.class);
Draw draw=new Draw((JChannel)fork_ch);
fork_ch.connect("ignored");
draw.go();
eventLoop();
}
The code in bold was inserted. So what does it do ? It grabs the JGroups channel from the Infinispan cache, creates a light-weight (fork) channel and runs Draw [5] over it. Draw is a replicated whiteboard GUI application. To explain this step-by-step:
- First the Transport instance is retrieved from the cache, then the JGroups channel from it
- Next a ForkChannel is created. It is passed the hijacked JGroups channel, the name of the newly created fork stack ("hijack-stack") and the name of the fork channel ("lead-hijacker"). Then we state that we want to dynamically insert a FORK protocol if it doesn't exist, above FRAG2. FORK [2] is needed to create fork channels
- Next, we create an instance of Draw (shipped with JGroups) on the newly created fork channel
- Then we connect the fork channel and call go() on Draw which starts up the GUI
The hijacked application is a text-based Infinispan perf test (shown in the 2 shell windows). The hijacking Draw windows are shown above. Pressing and moving the mouse around will send multicasts of coordinates/color around the cluster over the fork channel, but the hijacked channel will not notice anything.
Seem like we got away with hijacking the JGroups channel after all ! :-)
[1] http://www.jgroups.org/manual/html/user-advanced.html#ForkChannel
[2] https://issues.jboss.org/browse/JGRP-1613
[3] https://github.com/belaban/HijackTest
[4] https://github.com/belaban/HijackTest/blob/master/src/main/java/org/dubious/HijackTest.java#L53
[5] https://github.com/belaban/JGroups/blob/master/src/org/jgroups/demos/Draw.java
Forgot to mention that this required JGroups 3.4.0.Alpha2 or higher, which can be downloaded from https://sourceforge.net/projects/javagroups/files/JGroups/3.4.0.Alpha2/
ReplyDeleteHi Bela
ReplyDeleteI am using ForkChannel as you have described.
I am facing following issue: ISPN000220: Problems un-marshalling remote command from byte buffer
java.io.StreamCorruptedException: Unexpected byte found when reading an object: 0
It is happening when I am starting more Infinispan nodes at once and meanwhile also trying to connect to ForkChannel.
Can you help me how it can be handled right?
Thanks
I suggest post this to the JGroups mailing list with *more* information, e.g. a stack trace...
ReplyDeleteI've made post to
ReplyDeletehttp://jgroups.1086181.n5.nabble.com/jgroups-users-FORK-protocol-to-create-light-weight-channels-td9851.html
Oops, I didn't see this... Anyway, the stack trace looks like it's caused by the JBoss unmarshaller and not JGroups. Also, if you use FORK, it should show up in the trace, but it doesn't. What makes you think this exception was caused by FORK ?
ReplyDeleteYes you are right from stack trace it seems it is caused by JBoss unmarshaller.
ReplyDeleteI noticed this error when trying to connect to ForkChannel during time when other cluster member is connecting to main_channel (which is used in ForkChannel).
I thought this could be the issue.