JGroups(3)

转载自:http://whitesock.iteye.com/blog/199595

 

3 Building Blocks
    Building blocks位于org.jgroups.blocks包中,在逻辑上可以视为channels之上的一层,它提供了更复杂的接口。Building blocks并不必依赖于channels,部分building blocks只需要实现了Transport接口的类即可工作。以下简要介绍部分building blocks。

3.1 MessageDispatcher
    Channels 通常用于异步地发送和接收消息。然后有些情况下需要同步通信,例如发送者希望向集群发送消息并等待所有成员的应答,或者等待部分成员的应答。MessageDispatcher支持以同步或者异步的方式发送消息,它在构造时需要一个Channel型的参数。
    MessageDispatcher提供了Object handle(Message msg)方法,用于以push 方式的接收消息并返回应答(必须可以被序列化),该方法抛出的异常也会被传播到消息发送者。MessageDispatcher在内部使用了PullPushAdapter,PullPushAdapter也是org.jgroups.blocks包中的类,但是已经被标记为deprecated。这种方式被称为MessageDispatcher的server模式。
    MessageDispatcher的client模式是指通过调用castMessage或者sendMessage向集群发送消息并同步或者异步的等待应答。castMessage()方法向dests指定的地址发送消息,如果dest为null,那么向集群中所有成员发送消息。castMessage()方法的返回值是RspList,RspList 实现了Map<Address,Rsp> 接口。msg参数中的目的地址会被覆盖。mode参数(由org.jgroups.blocks.GroupRequest类定义)指定了消息是同步还是异步发送,其可选值如下:

  • GET_FIRST 返回收到的第一个应答。
  • GET_ALL 等待所有成员的应答(被怀疑崩溃的成员除外)。
  • GET_MAJORITY 等待绝大多数成员(相对与成员的个数)的应答。
  • GET_ABS_MAJORITY等待绝大多数成员(一个绝对的数值,只计算一次)的应答。
  • GET_N 等待n个应答,如果n大于成员的个数,可能会一直阻塞下去。
  • GET_NONE 不等待应答,直接返回,即异步方式。

    castMessage()方法的定义如下:

Java代码   收藏代码
  1. public RspList castMessage(Vector dests, Message msg, int mode, long timeout);  

    sendMessage()方法允许向一个成员发送消息,msg参数的目的地址不能为null。如果mode参数是GET_NONE,那么消息的发送变成异步方式;否则mode参数会被忽略(缺省采用GET_FIRST)。sendMessage()方法的定义如下:

Java代码   收藏代码
  1. public Object sendMessage(Message msg, int mode, long timeout) throws TimeoutException;  

    以下是个使用MessageDispatcher的例子:

Java代码   收藏代码
  1. import java.io.BufferedReader;  
  2. import java.io.InputStreamReader;  
  3.   
  4. import org.jgroups.Channel;  
  5. import org.jgroups.JChannel;  
  6. import org.jgroups.Message;  
  7. import org.jgroups.blocks.GroupRequest;  
  8. import org.jgroups.blocks.MessageDispatcher;  
  9. import org.jgroups.blocks.RequestHandler;  
  10. import org.jgroups.util.RspList;  
  11.   
  12. public class MessageDispatcherTest {  
  13.     //  
  14.     private Channel channel;  
  15.     private MessageDispatcher dispatcher;  
  16.     private boolean propagateException = false;  
  17.   
  18.     public void start() throws Exception {  
  19.         //  
  20.         channel = new JChannel();  
  21.         dispatcher = new MessageDispatcher(channel, nullnullnew RequestHandler() {  
  22.   
  23.             public Object handle(Message msg) {  
  24.                 System.out.println("got a message: " + msg);  
  25.                 if(propagateException) {  
  26.                     throw new RuntimeException("failed to handle message: " + msg.getObject());  
  27.                 } else {  
  28.                     return new String("success");  
  29.                 }  
  30.             }  
  31.               
  32.         });  
  33.         channel.connect("MessageDispatcherTest");  
  34.           
  35.         //  
  36.         sendMessage();  
  37.           
  38.         //  
  39.         channel.close();  
  40.         dispatcher.stop();  
  41.     }  
  42.       
  43.     private void sendMessage() throws Exception {  
  44.         boolean succeed = false;  
  45.         BufferedReader br = null;  
  46.         try {  
  47.             br = new BufferedReader(new InputStreamReader(System.in));  
  48.             while(true) {  
  49.                 System.out.print("> ");  
  50.                 System.out.flush();  
  51.                 String line = br.readLine();  
  52.                 if(line != null && line.equals("exit")) {  
  53.                     break;  
  54.                 } else {  
  55.                     Message msg = new Message(nullnull, line);  
  56.                     RspList rl = dispatcher.castMessage(null, msg, GroupRequest.GET_ALL, 0);  
  57.                     System.out.println("Responses:\n" + rl);  
  58.                 }  
  59.             }  
  60.             succeed = true;  
  61.         } finally {  
  62.             if(br != null) {  
  63.                 try {  
  64.                     br.close();  
  65.                 } catch (Exception e) {  
  66.                     if(succeed) {  
  67.                         throw e;  
  68.                     }  
  69.                 }  
  70.             }  
  71.         }  
  72.     }  
  73.   
  74.     public static void main(String[] args) {  
  75.         try {  
  76.             new MessageDispatcherTest().start();  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.     }  
  81. }  

3.2 RpcDispatcher
    RpcDispatcher 继承自MessageDispatcher,它允许远程调用集群中其它成员上的方法,并可选地等待应答。跟MessageDispatcher相比,不需要为RpcDispatcher指定RequestHandler。RpcDispatcher的构造函数接受一个Object server_obj参数,它是远程调用的目标对象。RpcDispatcher的callRemoteMethods系列方法用于远程调用目标对象上的方法,该方法可以由MethodCall指定,也可以通过方法名、参数类型指定。跟MessageDispatcher的castMessage()方法和sendMessage()方法类似,callRemoteMethods系列方法也接受一个int mode参数,其含义也相同。以下是个简单的例子:

Java代码   收藏代码
  1. import java.io.BufferedReader;  
  2. import java.io.InputStreamReader;  
  3.   
  4. import org.jgroups.Channel;  
  5. import org.jgroups.JChannel;  
  6. import org.jgroups.blocks.GroupRequest;  
  7. import org.jgroups.blocks.RpcDispatcher;  
  8. import org.jgroups.util.RspList;  
  9.   
  10. public class RpcDispatcherTest {  
  11.     private Channel channel;  
  12.     private RpcDispatcher dispatcher;  
  13.   
  14.     public int print(int number) throws Exception {  
  15.         return number * 2;  
  16.     }  
  17.   
  18.     public void start() throws Exception {  
  19.         channel = new JChannel();  
  20.         dispatcher = new RpcDispatcher(channel, nullnullthis);  
  21.         channel.connect("RpcDispatcherTest");  
  22.           
  23.         //  
  24.         sendMessage();  
  25.           
  26.         //  
  27.         channel.close();  
  28.         dispatcher.stop();  
  29.     }  
  30.       
  31.     private void sendMessage() throws Exception {  
  32.         boolean succeed = false;  
  33.         BufferedReader br = null;  
  34.         try {  
  35.             br = new BufferedReader(new InputStreamReader(System.in));  
  36.             while(true) {  
  37.                 System.out.print("> please input an int value:");  
  38.                 System.out.flush();  
  39.                 String line = br.readLine();  
  40.                 if(line != null && line.equals("exit")) {  
  41.                     break;  
  42.                 } else {  
  43.                     int param = 0;  
  44.                     try {  
  45.                         param = Integer.parseInt(line);  
  46.                     } catch(Exception e) {  
  47.                         System.out.println("invalid input: " + line);  
  48.                         continue;  
  49.                     }  
  50.                     RspList rl = dispatcher.callRemoteMethods(null"print"new Object[]{new Integer(param)}, new Class[]{int.class}, GroupRequest.GET_ALL, 0);  
  51.                     System.out.println("Responses: \n" + rl);  
  52.                 }  
  53.             }  
  54.             succeed = true;  
  55.         } finally {  
  56.             if(br != null) {  
  57.                 try {  
  58.                     br.close();  
  59.                 } catch (Exception e) {  
  60.                     if(succeed) {  
  61.                         throw e;  
  62.                     }  
  63.                 }  
  64.             }  
  65.         }  
  66.     }  
  67.   
  68.     public static void main(String[] args) {  
  69.         try {  
  70.             new RpcDispatcherTest().start();  
  71.         } catch (Exception e) {  
  72.             e.printStackTrace();  
  73.         }  
  74.     }  
  75. }  

3.3 ReplicatedHashMap
    ReplicatedHashMap 继承自ConcurrentHashMap,并在内部使用了RpcDispatcher。ReplicatedHashMap构造函数的clustername参数指定了集群的名字,集群中所有的实例会包含相同的状态。新加入的实例在开始工作前会从集群中获得当前的状态。对实例的修改(例如通过put,remove方法)会传播到集群的其它实例中,只读的请求(例如get方法)则是本地调用。需要注意的是,ReplicatedHashMap的以下划线开头的方法是用于RpcDispatcher的远程调用的。在ReplicatedHashMap上可以注册 Notification,以便在实例的状态改变时进行回调,所有的回调也是本地的。以下是个简单的例子:

Java代码   收藏代码
  1. import java.io.BufferedReader;  
  2. import java.io.InputStreamReader;  
  3. import java.util.Iterator;  
  4. import java.util.Map;  
  5. import java.util.Vector;  
  6.   
  7. import org.jgroups.Address;  
  8. import org.jgroups.ChannelFactory;  
  9. import org.jgroups.JChannelFactory;  
  10. import org.jgroups.View;  
  11. import org.jgroups.blocks.ReplicatedHashMap;  
  12.   
  13. public class ReplicatedHashMapTest implements ReplicatedHashMap.Notification<String, String> {  
  14.     //  
  15.     private ReplicatedHashMap<String, String> map;  
  16.   
  17.     public void start() throws Exception {  
  18.         ChannelFactory factory = new JChannelFactory();  
  19.         map = new ReplicatedHashMap<String, String>("ReplicatedHashMapTest", factory, "udp.xml"false10000);  
  20.         map.addNotifier(this);  
  21.   
  22.         sendMessage();  
  23.         map.stop();  
  24.     }  
  25.   
  26.     public void entryRemoved(String key) {  
  27.         System.out.println("in entryRemoved(" + key + ")");  
  28.     }  
  29.   
  30.     public void entrySet(String key, String value) {  
  31.         System.out.println("in entrySet(" + key + "," + value + ")");  
  32.     }  
  33.   
  34.     public void contentsSet(Map<String, String> m) {  
  35.         System.out.println("in contentsSet(" + printMap(m) + ")");  
  36.     }  
  37.   
  38.     public void contentsCleared() {  
  39.         System.out.println("in contentsCleared()");  
  40.     }  
  41.   
  42.     public void viewChange(View view, Vector<Address> newMembers,  
  43.             Vector<Address> oldMembers) {  
  44.         System.out.println("in viewChange(" + view + ")");  
  45.     }  
  46.   
  47.     private void sendMessage() throws Exception {  
  48.         boolean succeed = false;  
  49.         BufferedReader br = null;  
  50.         try {  
  51.             br = new BufferedReader(new InputStreamReader(System.in));  
  52.             while (true) {  
  53.                 System.out.print("> ");  
  54.                 System.out.flush();  
  55.                 String line = br.readLine();  
  56.                 if (line != null && line.equals("exit")) {  
  57.                     break;  
  58.                 } else {  
  59.                     if (line.equals("show")) {  
  60.                         System.out.println(printMap(map));  
  61.                     } else if (line.equals("clear")) {  
  62.                         map.clear();  
  63.                     } else if (line.startsWith("remove ")) {  
  64.                         String key = line.substring(line.indexOf(" ") + 1, line.length()).trim();  
  65.                         map.remove(key);  
  66.                     } else if (line.startsWith("put ")) {  
  67.                         line = line.replace("put """);  
  68.                         int index = line.indexOf("=");  
  69.                         if (index <= 0 || index >= (line.length() - 1)) {  
  70.                             System.out.println("invalid input");  
  71.                             continue;  
  72.                         }  
  73.                         String key = line.substring(0, index).trim();  
  74.                         String value = line.substring(index + 1, line.length())  
  75.                                 .trim();  
  76.                         map.put(key, value);  
  77.                     } else {  
  78.                         System.out.println("invalid input: " + line);  
  79.                         continue;  
  80.                     }  
  81.                 }  
  82.             }  
  83.             succeed = true;  
  84.         } finally {  
  85.             if (br != null) {  
  86.                 try {  
  87.                     br.close();  
  88.                 } catch (Exception e) {  
  89.                     if (succeed) {  
  90.                         throw e;  
  91.                     }  
  92.                 }  
  93.             }  
  94.         }  
  95.     }  
  96.   
  97.     private String printMap(Map<String, String> m) {  
  98.         StringBuffer sb = new StringBuffer();  
  99.         sb.append("[");  
  100.         for (Iterator<String> iter = map.keySet().iterator(); iter.hasNext();) {  
  101.             String key = iter.next();  
  102.             String value = map.get(key);  
  103.             sb.append(key).append("=").append(value);  
  104.             if (iter.hasNext()) {  
  105.                 sb.append(",");  
  106.             }  
  107.         }  
  108.         sb.append("]");  
  109.         return sb.toString();  
  110.     }  
  111.   
  112.     public static void main(String args[]) {  
  113.         try {  
  114.             new ReplicatedHashMapTest().start();  
  115.         } catch (Exception e) {  
  116.             e.printStackTrace();  
  117.         }  
  118.     }  
  119. }  

3.4 NotificationBus
    NotificationBus 提供了向集群发送通知的能力,通知可以是任何可以被序列化的对象。NotificationBus在内部使用Channel,其start()和stop()方法用于启动和停止。NotificationBus的setConsumer()方法用于注册Consumer接口,其定义如下:

Java代码   收藏代码
  1. public interface Consumer {  
  2.     void handleNotification(Serializable n);  
  3.     Serializable getCache();  
  4.     void memberJoined(Address mbr);  
  5.     void memberLeft(Address mbr);  
  6. }  

    NotificationBus的getCacheFromCoordinator() 和getCacheFromMember()用于请求集群的状态。前者是从coordinator得到状态,后者从指定地址的成员处得到状态。NotificationBus上注册的Consumer需要实现getCache()方法以返回状态。以下是个简单的例子:

Java代码   收藏代码
  1. import java.io.BufferedReader;  
  2. import java.io.InputStreamReader;  
  3. import java.io.Serializable;  
  4. import java.util.Iterator;  
  5. import java.util.LinkedList;  
  6.   
  7. import org.jgroups.Address;  
  8. import org.jgroups.blocks.NotificationBus;  
  9.   
  10. public class NotificationBusTest implements NotificationBus.Consumer {  
  11.     //  
  12.     private NotificationBus bus;  
  13.     private LinkedList<Serializable> cache;  
  14.   
  15.     public void handleNotification(Serializable n) {  
  16.         System.out.println("in handleNotification(" + n + ")");  
  17.         if (cache != null) {  
  18.             cache.add(n);  
  19.         }  
  20.     }  
  21.   
  22.     public Serializable getCache() {  
  23.         return cache;  
  24.     }  
  25.   
  26.     public void memberJoined(Address mbr) {  
  27.         System.out.println("in memberJoined(" + mbr + ")");  
  28.     }  
  29.   
  30.     public void memberLeft(Address mbr) {  
  31.         System.out.println("in memberLeft(" + mbr + ")");  
  32.     }  
  33.   
  34.     @SuppressWarnings("unchecked")  
  35.     public void start() throws Exception {  
  36.         //  
  37.         bus = new NotificationBus("NotificationBusTest"null);  
  38.         bus.setConsumer(this);  
  39.         bus.start();  
  40.         cache = (LinkedList<Serializable>) bus.getCacheFromCoordinator(30001);  
  41.         if (cache == null) {  
  42.             cache = new LinkedList<Serializable>();  
  43.         }  
  44.         System.out.println(printCache(cache));  
  45.   
  46.         //  
  47.         sendNotification();  
  48.   
  49.         //  
  50.         bus.stop();  
  51.     }  
  52.   
  53.     private void sendNotification() throws Exception {  
  54.         boolean succeed = false;  
  55.         BufferedReader br = null;  
  56.         try {  
  57.             br = new BufferedReader(new InputStreamReader(System.in));  
  58.             while (true) {  
  59.                 System.out.print("> ");  
  60.                 System.out.flush();  
  61.                 String line = br.readLine();  
  62.                 if (line != null && line.equals("exit")) {  
  63.                     break;  
  64.                 } else {  
  65.                     bus.sendNotification(line);  
  66.                 }  
  67.             }  
  68.             succeed = true;  
  69.         } finally {  
  70.             if (br != null) {  
  71.                 try {  
  72.                     br.close();  
  73.                 } catch (Exception e) {  
  74.                     if (succeed) {  
  75.                         throw e;  
  76.                     }  
  77.                 }  
  78.             }  
  79.         }  
  80.     }  
  81.   
  82.     private String printCache(LinkedList<Serializable> c) {  
  83.         StringBuffer sb = new StringBuffer();  
  84.         sb.append("[");  
  85.         for (Iterator<Serializable> iter = c.iterator(); iter.hasNext();) {  
  86.             sb.append(iter.next());  
  87.             if (iter.hasNext()) {  
  88.                 sb.append(",");  
  89.             }  
  90.         }  
  91.         sb.append("]");  
  92.         return sb.toString();  
  93.     }  
  94.   
  95.     public static void main(String[] args) {  
  96.         try {  
  97.             new NotificationBusTest().start();  
  98.         } catch (Exception e) {  
  99.             e.printStackTrace();  
  100.         }  
  101.     }  
  102. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值