如下图
三台JBoss(node1, node2, node3)组成的集群(其中node1为协调者),新节点node4加入集群,JBoss集群中所有节点状态要保持一致,这就需要node4从集群的协调者node1交换状态,交换状态过程使用JGroups,本文通过实验测试JBoss集群中新节点加入状态交换过程,以及群组通信的成员获取群组状态的过程,明白JBoss集群中新节点加入状态交换原理。测试群组通信状态交换的吞吐量等。我们分下面六个方面介绍:
本实验集群中有两个成员: node1,node2,node1 为协调者(第一个启动)作为状态提供者,node2 作为状态变化请求者通过 Channel.getState() 发送状态交换请求给集群,集群协调者node1负责将集群状态交换给node2。
1. 使用JBoss Cluster Framework Demo 介绍所示的方法,任意从SourceForge下载或编译生成DEMO_HOME,本测试的测试程序启动脚本位于DEMO_HOME/bin下
2. 启动node1,node1将作为状态提供者,也是集群中两个节点的协调者,我们使用启动脚本启动时需要附件-provider,同时我们必须指定jGroups配置文件和节点的名字,我们使用DEMO_HOME/conf下config.xml为状态交换实现的jGroups配置文件,node1为节点名字,同样我们也可指定要交换状态的大小,具体使用如下参数启动:
./largestate.sh -size 10000000 -provider -name node1 -props config.xml
3. 启动node2,node2为状态交换的请求者,类似于启动状态提供者节点,我们必须指定jGroups配置文件和节点的名字,且配置文件与状态提供者指定的配置文件相同,名字与状态提供者不同,这里我们同样使用DEMO_HOME/conf下config.xml为状态交换实现的jGroups配置文件,node2为状态交换的请求者节点名字,交换状态的大小我们也可以通过启动参数指定,我们可以使用如下命令启动:
./largestate.sh -size 10000000 -name node2 -props config.xml
https://github.com/kylinsoong/cluster/.../LargeState.java
使用实验步骤说明中的步骤进行实验操作,通过node1及node2输出的日志我们可以总结状态交换的具体过程如下图所示:
如上图所示,状态交换一般可以分为以下四步:
使用实验步骤说明中的步骤进行实验,使用-size指定状态交换的大小为100MB,状态交换完成后在状态请求者node2端会输出状态交换的总时间,如下为我测试中的输出:
[2013-04-27 15:50:29,981] <-- received 100MB in 841ms
JBoss集群具有高可用及容错的功能是因为JBoss集群底层使用jGroups进行状态复制。JBoss集群中如果某一节点发生异常,重启节点的过程中会进行状态交换,常见可能发生错误包括:状态提供者getState(OutputStream ostream)实现将状态以输出流的方式写出时出错;状态接收者setState(InputStream istream)实现以输入流的方式接收状态时出错。本实验也可以模拟这两种种情况,具体在启动状态提供者时附加-provider_fails启动参数,或在启动状态接收者时附加-requester_fails启动参数,如下所示:
./largestate.sh -size 100000000 -provider -name node1 -props config.xml -provider_fails ./largestate.sh -size 100000000 -name node2 -props config.xml -requester_fails
org.jgroups.StateTransferException: state transfer failed at org.jgroups.JChannel.getState(JChannel.java:584) at org.jgroups.JChannel.getState(JChannel.java:512)