RPC (Remote Procedure Call) with JGroup
posted at April 8, 2012 with tags java, jgroups

JGroups constitutes a perfect medium for RPC between nodes in a cluster. Here, I share a very basic JGroups RPC example.

import org.jgroups.Address;
import org.jgroups.JChannel;
import org.jgroups.blocks.*;
import org.jgroups.util.RspList;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public final class RpcPeer {
    private final JChannel rpcChannel;
    private final RpcDispatcher rpcDispatcher;
    private final RequestOptions requestOptions;

    private static final Map<Short, Method> methods;

    private static final short CALLABLE = 0;

    static {
        methods = new HashMap<Short, Method>();
        try {
            methods.put(CALLABLE, RpcPeer.class.getMethod("callable", Long.class));
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    RpcPeer() throws Exception {
        rpcChannel = ChannelFactory.getInstance().create();
        rpcDispatcher = new RpcDispatcher(rpcChannel, this);
        rpcDispatcher.setMethodLookup(new MethodLookup() {
            public Method findMethod(short id) {
                return methods.get(id);
            }
        });
        requestOptions = new RequestOptions(ResponseMode.GET_ALL, 3000);
    }

    public void connect(String name) throws Exception {
        rpcChannel.connect(name);
    }

    public void disconnect() {
        rpcChannel.disconnect();
        rpcChannel.close();
    }

    @SuppressWarnings("unused")
    public String callable(Long n) {
        return String.format("%s received %s.", rpcChannel.getAddress(), n);
    }

    public Long call(Address address, Long n) throws Exception {
        MethodCall methodCall = new MethodCall(CALLABLE, (long) 10);
        return rpcDispatcher.callRemoteMethod(
                address, methodCall, requestOptions);
    }

    public RspList<Object> call(Long n) throws Exception {
        MethodCall methodCall = new MethodCall(CALLABLE, n);
        return rpcDispatcher.callRemoteMethods(
                null, methodCall, requestOptions);
    }
}

I think (at least, hope) the code is self-explanatory. A minor important point here is the RPC channel. Per see, I use ChannelFactory.getInstance().create() method to create the channel. ChannelFactory is a shortcut class to create multiple channels sharing the same transport. (See my Shared Transport in JGroups post for details.) That is, you need to have a separate JGroups channel reserved for RPC communication. All other messages sent/received using this channel will be consumed and ignored by the RpcDispatcher.