内容概要

本部分说明JGroups构建块接口MessageDispatcher,具体提供一个简单示例来说明如何使用JGroups构建块MessageDispatcher 构建群组通信应用

示例描述

构建块基于通道之上,是对通道API的更高层抽象,MessageDispatcher提供异步和同步的方法发送消息给集群中的成员并等待响应,我们知道直接使用jGroups API可以向群组发送消息,或从群组接收消息,但发送和接收之间没有任何联系,而使用MessageDispatcher发送消息和接收消息是在同一个事务中完成。本示例演示使用MessageDispatcher 发送消息到集群所有成员并等待响应,验证 GET_ALL 响应模式,超时时间等属性。

示例步骤

本示例集群中有三个成员node1,node2 和node3,node1 为协调者(第一个加入集群)负责集群视图的更新。三个节点都是做相同的事情,向集群中所有节点发送一条消息,并等待接收响应消息。使用JBoss Cluster Framework Demo 介绍所示的方法,任意从SourceForge下载或编译生成DEMO_HOME,本示例的启动脚本msgDispatcher.sh位于DEMO_HOME/bin下。接下来我们依次启动三个节点:

./msgDispatcher.sh -n node1
./msgDispatcher.sh -n node2
./msgDispatcher.sh -n node3

注意,-n指定一个节点名字,Windows操作系统使用对应.bat脚本。

结果分析

1. node1,node2 和node3中任何一个节点启动后我们都可以看到发送消息到群组的日志信息,如下为node1上输出的日志:

16:36:43,699 INFO  [MessageDispatcherTest] Casting message to all group members

2. node1,node2 和node3中任何一个节点启动发送完消息后都可以看到群组中返回消息的输出信息,如下为node3上打印输出的响应消息:

Responses:
node3-MessageDispatcher Test Message
node2-MessageDispatcher Test Message
node1-MessageDispatcher Test Message

我们可以看到node3节点打印输出的响应消息有三条,及集群中的所有节点都收到node3发送的消息,且集群中所有节点发送的响应消息都被node3收到。我们可以通过响应模式来控制是否消息发送者要等待所有节点的响应消息,本示例中使用的是 GET_ALL 响应模式,所以只有当接收到所有节点的响应消息或等待超时抛出异常才终止。

3. node1,node2 和node3中任何一个节点启动后的日志中我们可以看到MyRequestHandler处理消息输出的日志,如下为node1上输出的日志:

16:37:11,839 INFO  [MyRequestHandler] node3, MessageDispatcher Test Message

4. node1,node2 和node3中任何一个节点运行的日志中我们可以看到MyMembershipListener输出的日志,当群组成员关系发生变化是群视图被打印输出,如下为node1上输出的日志信息:

16:37:11,655 INFO  [MyMembershipListener] ViewAccepted, [node1|2] [node1, node2, node3]

[node1|2] [node1, node2, node3]为打印输出的群组视图,node1|2 表示群组的协调者为node1,竖线后面的2表示视图被更新了3次(node1|0,node1|1,node1|2);视图中共有三个成员,即node1,node2 和node3。

代码分析

本示例所有的源代码可以在cluster/jgroups/stu/src/main/java/.../blocks下找到,接下来我们从代码的层面去解释上面的分析结果,这样有助于更直观的理解构建块MessageDispatcher的理解:

47                 channel = new JChannel(props);
48 if(null != name) {
49 channel.setName(name);
50 }
51 handler = new MyRequestHandler(channel);
52 messageListener = new MyMessageListener();
53 membershipListener = new MyMembershipListener();
55 disp = new MessageDispatcher(channel, messageListener, membershipListener, handler);
56 channel.connect("MessageDispatcherTestGroup");
58 Util.sleep(100);
59 logger.info("Casting message to all group members");
60 Message message = new Message(null, null, new String("MessageDispatcher Test Message"));
61 rsp_list = disp.castMessage(null, message, new RequestOptions().setMode(ResponseMode.GET_ALL).setTimeout(0));
63 System.out.println("Responses:");
65 List list = rsp_list.getResults();
66 for(Object obj : list) {
67 System.out.println(" " + obj);
68 }

如上47-50行创建一个,设定相应节点的名字;55行实例化一个 MessageDispatcher,我们可以看到,构建块接口是基于通道之上,是对通道的更高层抽象,所以创建 MessageDispatcher时需要传递一个实例化的通道(channel),MessageDispatcher 实例化后通道开始连接到群组(如56行所示);59-61行创建一个消息,通过 castMessage()方法将消息发送到群组,注意,目的地址为空,所以消息接收者为群组所有成员,响应模式为 GET_ALL,所以发送者等待所有成员响应后 castMessage()方法返回,超时时间为 0,即castMessage一直出于等待状态知道所有节点响应消息返回或超时抛出异常;65-68行打印输出所有响应返回消息。

9 public class MyRequestHandler implements RequestHandler {
...
20 public Object handle(Message msg) throws Exception {
21 Address sender = msg.getSrc();
22 logger.info(sender + ", " + msg.getObject());
23 return channel.getName() + "-" + msg.getObject();
24 }
25
26 }

如上第9行,MyRequestHandler实现RequestHandler接口,RequestHandler定义了handle方法,用来处理接收到的消息,20-24行为我们实现的handle方法,我们在日志中记录消息发送者的名字和消息的内容(结果分析第3点node1输出的日志“node3, MessageDispatcher Test Message”表示消息发送着是node3,消息的内容是“MessageDispatcher Test Message”),并将自己的名字和接收到消息的内容返回(结果分析第2点node3输出的日志包括“node1-MessageDispatcher Test Message”表示该响应消息是从node1返回的)。

8 public class MyMembershipListener implements MembershipListener {
...
12 public void viewAccepted(View view) {
13 logger.info("ViewAccepted, " + view);
14 }

如上第8行表示MyMembershipListener实现了MembershipListener接口,MembershipListener接口定义一些成员控制的方法,这里我们实现了viewAccepted()方法,即当群组成员发生变化时该方法被调运,记录群组视图到日志中。

JBoss 系列十七:使用JGroups构建块MessageDispatcher 构建群组通信应用的更多相关文章

  1. JBoss 系列十九:使用JGroups构建块RspFilter对群组通信返回消息进行过滤

    内容概述 本部分说明JGroups构建块接口RspFilter,具体提供一个简单示例来说明如何使用JGroups构建块RspFilter对群组通信返回消息进行过滤. 示例描述 我们知道构建块基于通道之 ...

  2. JBoss 系列十八:使用JGroups构建块RpcDispatcher构建群组通信应用

    内容概要 本部分说明JGroups构建块接口RpcDispatcher,具体提供一个简单示例来说明如何使用JGroups构建块RpcDispatcher构建群组通信应用. 示例描述 类似Message ...

  3. 企业架构研究总结(35)——TOGAF架构内容框架之构建块(Building Blocks)

    之前忙于搬家移居,无暇顾及博客,今天终于得闲继续我的“政治课”了,希望之后至少能够补完TOGAF方面的内容.从前面文章可以看出,笔者并无太多能力和机会对TOGAF进行理论和实际的联系,仅可对标准的文本 ...

  4. TOGAF架构内容框架之构建块(Building Blocks)

    TOGAF架构内容框架之构建块(Building Blocks) 之前忙于搬家移居,无暇顾及博客,今天终于得闲继续我的“政治课”了,希望之后至少能够补完TOGAF方面的内容.从前面文章可以看出,笔者并 ...

  5. Web 前端开发精华文章集锦(jQuery、HTML5、CSS3)【系列十七】

    <Web 前端开发精华文章推荐>2013年第五期(总第十七期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HTML5 和 C ...

  6. JavaScript是如何工作的:Web Workers的构建块 + 5个使用他们的场景

    摘要: 理解Web Workers. 原文:JavaScript是如何工作的:Web Workers的构建块 + 5个使用他们的场景 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这 ...

  7. 爬虫入门系列(三):用 requests 构建知乎 API

    爬虫入门系列目录: 爬虫入门系列(一):快速理解HTTP协议 爬虫入门系列(二):优雅的HTTP库requests 爬虫入门系列(三):用 requests 构建知乎 API 在爬虫系列文章 优雅的H ...

  8. 线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步

    假设多个线程共享一个静态变量,如果让每个线程都执行相同的方法每次让静态变量自增1,这样的做法线程安全吗?能保证自增变量数据同步吗?本篇体验使用lock语句块和Interlocked类型方法保证自增变量 ...

  9. 现代前端库开发指南系列(二):使用 webpack 构建一个库

    前言 在前文中,我说过本系列文章的受众是在现代前端体系下能够熟练编写业务代码的同学,因此本文在介绍 webpack 配置时,仅提及构建一个库所特有的配置,其余配置请参考 webpack 官方文档. 输 ...

随机推荐

  1. BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 9280  Solved: 2421 ...

  2. Codeforces 1082 D. Maximum Diameter Graph-树的直径-最长链-构造题 (Educational Codeforces Round 55 (Rated for Div. 2))

    D. Maximum Diameter Graph time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  3. HDU 1016.Prime Ring Problem-素数环,相邻两数和为素数-DFS

    Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  4. shell 倒引号

    `command` 倒引号 (backticks) 在前面的单双引号,括住的是字串,但如果该字串是一列命令列,会怎样?答案是不会执行.要处理这种情况,我们得用倒单引号来做. fdv=`date +%F ...

  5. 解决cordova命令行方式下build或者run的时候报错问题

    phonegap3.0之后就将项目的生成方式做了很大的更改,原来是在eclipse里面修改生成并编译运行,但是3.0之后它的目录结构发生了很大变化,只修改主目录下面的index.html如果不buil ...

  6. WebService数据示例

    通过webservice提交xml数据以及soap协议的使用 上次已经给大家分享了简单的webservice的使用,提交给服务器的数据只是简单类型的数据,这次呢换成了xml,并通过一个小例子来讲解so ...

  7. [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)

    差分之后就是求多串LCS. 对其中一个串建SAM,然后把其它串放在上面跑. 对SAM上的每个状态都用f[x]记录这个状态与当前串的最长匹配长度,res[x]是对每次的f[x]取最小值.答案就是res[ ...

  8. 【数论】【莫比乌斯反演】【线性筛】bzoj2301 [HAOI2011]Problem b

    对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 100%的数据满足:1≤n≤50000,1≤a≤b ...

  9. [转]spring tx:advice 和 aop:config 配置事务

      <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www. ...

  10. 大于非负整数N的第一个回文数 Symmetric Number

    1.题目 如标题,求大于整数N(N>=0)的第一个回文数的字符串表示形式. 2.样例 1  --> 2 9  -->11 12345 -->12421 123456 --> ...