- 浏览: 483852 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
龘龘龘:
TrueBrian 写道有个问题,Sample 1中,为了控制 ...
What's New on Java 7 Phaser -
龘龘龘:
楼主总结的不错。
What's New on Java 7 Phaser -
TrueBrian:
有个问题,Sample 1中,为了控制线程的启动时机,博主实际 ...
What's New on Java 7 Phaser -
liguanqun811:
不知道楼主是否对zookeeper实现的分布式锁进行过性能测试 ...
Distributed Lock -
hobitton:
mysql的get lock有版本限制,否则get lock可 ...
Distributed Lock
2 API
2.1 Interfaces
2.1.1 Transport
Transport接口只定义了最简单的方法,用于发送和接收消息。其定义如下:
public interface Transport { void send(Message msg) throws Exception; Object receive(long timeout) throws Exception; }
2.1.2 MessageListener
如果说Transport接口是以pull的方式接收消息,那么MessageListener则是以push的方式处理消息。当收到消息时,receive方法会被调用。getState() 和setState()方法用于在实例间传递状态。其定义如下:
public interface MessageListener { void receive(Message msg); byte[] getState(); void setState(byte[] state); }
2.1.3 ExtendedMessageListener
ExtendedMessageListener继承自MessageListener,它定义了用来在实例间部分传递状态的方法。如果需要传递的状态数据量很大,那么通过配置协议栈,也可以指定使用流的方式传递状态。其定义如下:
public interface ExtendedMessageListener extends MessageListener { byte[] getState(String state_id); void setState(String state_id, byte[] state); void getState(OutputStream ostream); void setState(InputStream istream); void getState(String state_id, OutputStream ostream); void setState(String state_id, InputStream istream); }
2.1.4 MembershipListener
当收到view、suspicion message和block event 的时候,相应的方法会被调用。这个接口常用的方法是viewAccepted(),以便在新的实例加入(或者离开)到集群时得到通知。当JGroups推测某个实例可能崩溃时(此时该实例并未离开集群),suspect()方法会被调用,目前没有unsuspect()方法。当JGroups需要通知集群中的实例不要发送消息时,block()方法会被调用。这通常需要配置FLUSH协议,例如为了确保在进行状态传递的时候,没有实例在发送消息。在block()方法返回后,所有发送消息的线程都会被阻塞,知道FLUSH协议解除阻塞。需要注意的是,block()方法内不应该执行耗时的操作,否则整个FLUSH协议都会被阻塞。其定义如下:
public interface MembershipListener { void viewAccepted(View new_view); void suspect(Address suspected_mbr); void block(); }
2.1.5 ExtendedMembershipListener
ExtendedMembershipListener继承自MembershipListener。当FLUSH协议解除阻塞的时候,unblock()方法会被调用,所有发送消息的线程可以继续发送消息。其定义如下:
public interface ExtendedMembershipListener extends MembershipListener { void unblock(); }
2.1.6 ChannelListener
可以通过调用JChannel接口的addChannelListener(ChannelListener listener)方法来添加ChannelListener。当Channel被连接或者关闭时,相应的方法会北调用。其定义如下:
public interface ChannelListener { void channelConnected(Channel channel); void channelDisconnected(Channel channel); void channelClosed(Channel channel); void channelShunned(); void channelReconnected(Address addr); }
2.1.7 Receiver
Receiver继承自MessageListener和MembershipListener。其定义如下:
public interface Receiver extends MessageListener, MembershipListener { }
2.1.8 ExtendedReceiver
ExtendedReceiver继承自Receiver、ExtendedMessageListener和ExtendedMembershipListener。其定义如下:
public interface ExtendedReceiver extends Receiver, ExtendedMessageListener, ExtendedMembershipListener { }
2.2 Channel
2.2.1 Creating a channel
最常见的创建Channel的方法是通过构造函数,此外也可以通过工厂方法。需要注意的是,集群中所有的实例必须有相同的协议栈。JChannel的构造函数之一如下:
public JChannel(String properties) throws ChannelException { this(ConfiguratorFactory.getStackConfigurator(properties)); }
以上的构造函数中,properties参数是冒号分割的字符串,用来配置协议栈。字符串的最左端的元素定义了最底层的协议。如果properties为null,那么将使用缺省的协议栈,即jgroups-all.jar中的udp.xml。以下是个properties参数的例子:
String props="UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=32):" + "PING(timeout=3000;num_initial_members=6):" + "FD(timeout=5000):" + "VERIFY_SUSPECT(timeout=1500):" + "pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):" + "UNICAST(timeout=300,600,1200):" + "FRAG:" + "pbcast.GMS(join_timeout=5000;shun=false;print_local_addr=true)";
此外,也可以用File和URL作为构造函数的参数,这种方式允许以本地或者远程的XML文件配置协议栈。XML文件的config节点中的每个子节点定义一个协议,第一个子节点定义了最底层的协议。每个子节点名都对应一个Java类名,缺省的协议名不必是全限定类名,它们位于org.jgroups.stack.protocols包中。如果是自定义的协议,那么则必须是全限定类名。每个协议可以有零个或多个属性,以name/value对的方式指定。以下是jgroups-all.jar中的udp.xml的内容:
<config> <UDP mcast_addr="${jgroups.udp.mcast_addr:228.10.10.10}" mcast_port="${jgroups.udp.mcast_port:45588}" tos="8" ucast_recv_buf_size="20000000" ucast_send_buf_size="640000" mcast_recv_buf_size="25000000" mcast_send_buf_size="640000" loopback="false" discard_incompatible_packets="true" max_bundle_size="64000" max_bundle_timeout="30" use_incoming_packet_handler="true" ip_ttl="${jgroups.udp.ip_ttl:2}" enable_bundling="true" enable_diagnostics="true" thread_naming_pattern="cl" use_concurrent_stack="true" thread_pool.enabled="true" thread_pool.min_threads="2" thread_pool.max_threads="8" thread_pool.keep_alive_time="5000" thread_pool.queue_enabled="true" thread_pool.queue_max_size="1000" thread_pool.rejection_policy="Run" oob_thread_pool.enabled="true" oob_thread_pool.min_threads="1" oob_thread_pool.max_threads="8" oob_thread_pool.keep_alive_time="5000" oob_thread_pool.queue_enabled="false" oob_thread_pool.queue_max_size="100" oob_thread_pool.rejection_policy="Run"/> <PING timeout="2000" num_initial_members="3"/> <MERGE2 max_interval="30000" min_interval="10000"/> <FD_SOCK/> <FD timeout="10000" max_tries="5" shun="true"/> <VERIFY_SUSPECT timeout="1500" /> <BARRIER /> <pbcast.NAKACK use_stats_for_retransmission="false" exponential_backoff="150" use_mcast_xmit="true" gc_lag="0" retransmit_timeout="50,300,600,1200" discard_delivered_msgs="true"/> <UNICAST timeout="300,600,1200"/> <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000" max_bytes="1000000"/> <VIEW_SYNC avg_send_interval="60000" /> <pbcast.GMS print_local_addr="true" join_timeout="3000" shun="false" view_bundling="true"/> <FC max_credits="500000" min_threshold="0.20"/> <FRAG2 frag_size="60000" /> <!--pbcast.STREAMING_STATE_TRANSFER /--> <pbcast.STATE_TRANSFER /> <!-- pbcast.FLUSH /--> </config>
以上XML文件中,UDP协议的mcast_addr属性被指定使用jgroups.udp.mcast_addr系统属性,如果没有配置这个系统属性,那么使用缺省值228.10.10.10。
2.2.2 Setting options
通过setOpt(int option, Object value)方法可以给Channel设置属性,目前支持的属性有:
- Channel.BLOCK 这是一个Boolean型的属性,缺省是false。如果设置成true,那么会接收到block message。
- Channel.LOCAL这是一个Boolean型的属性,缺省设置成true。如果是true,那么当集群中的实例向集群发送消息时,这个实例本身也会收到这个消息。
- Channel.AUTO_RECONNECT这是一个Boolean型的属性,缺省是false。如果设置成true,那么shunned channel 在离开集群后,会自动重新加入到集群中。
- Channel.AUTO_GETSTATE 这是一个Boolean型的属性,缺省是false。如果设置成true,那么shunned channel在自动重新加入到集群后,会自动尝试向集群的coordinator 获得集群的状态(需要AUTO_RECONNECT也设置成true)。
通过Object getOpt(int option)可以或者channel的相关属性值。
2.2.3 Connecting/Disconnecting
通过调用connect(String cluster_name) throws ChannelException方法连接到集群。cluster_name参数指定了集群的名称。集群中的第一个实例被称为coordinator。当集群中的成员发生变化的时候,coordinator会向集群中的其它实例发送view message。
也可以通过调用void connect(String cluster_name, Address target, String state_id,long timeout) throws ChannelException方法连接到集群,并从集群中请求当前的状态。与将这两个操作分开进行相比,在一个方法调用内完成这两个操作,可以允许JGroups对发送的消息进行优化,更重要的是,从调用者角度来看,这两个操作被合并成一个原子操作。cluster_name参数用于指定集群的名称。target参数指定了从集群中的哪个实例获得状态,如果该参数为null,那么会从coordinator获得。如果希望传递部分的状态,那么state_id参数可以用于指定状态id。
当Channel连接到集群后,通过调用String getClusterName()方法可以获得当前连接到的集群名称。通过调用Address getLocalAddress()方法可以获得channel的地址。通过调用View getView()方法可以获得channel的当前view。每当Channel收到view message的时候,channel的当前view就会被更新。
通过调用void disconnect()方法以断开到集群的连接。如果channel已经并没有连接到集群,或者chaneel已经被close,那么调用这个方法没有任何效果。如果channel已经连接到集群,那么这个方法内会向coordinator发送一个离开请求,同时coordinator会向集群中的所有其它实例发送view message,以通知它们该实例的离开。断开连接的channel可以通过调用connect()方法重新连接到集群。
通过void close()方法以释放channel占有的资源。Channel被close之后,调用channel上的任何方法都可能会导致异常。
2.2.4 Sending messages
当channel连接到集群后,可以通过以下方法发送消息。第一个send方法接受一个Message型的参数,如果msg的目标地址不是null,那么消息会发送到指定地址,否则会发送到集群内的所有成员。msg的源地址可以不必手工设置,如果是null,那么会被协议栈的最底层协议(传输协议)设置成channel的本地地址。第二个send方法在内部使用了一个send方法。
void send(Message msg) throws ChannelNotConnectedException, ChannelClosedException void send(Address dst, Address src, Serializable obj) throws ChannelNotConnectedException, ChannelClosedException
以下是个发送消息的例子:
Hashtable data; try { Address receiver=channel.getView().getMembers().first(); channel.send(receiver, null, data); } catch(Exception ex) { // handle errors }
2.2.5 Receiving messages
Channel 以异步的方式从网络上接收消息,然后把消息存放在一个无界队列中。当调用receive()方法时,会尝试返回队列中取得下一个可用的消息。如果队列中没有消息,那么会被阻塞。如果timeout小于等于零,那么会永远等待下去;否则会等待timeout指定的毫秒数,直到收到消息或者抛出TimeoutException。需要注意的是,JChannel. receive(long timeout)方法已经被标记为deprecated。根据channel options的不同,receive()方法可能返回以下类型的对象:
- Message 普通消息。Message.makeReply()可以同于创建消息的应答,即以当前消息的源地址作为应答消息的目标地址。
- View 当集群的成员发生变化的时候,集群的每个成员都会收到view message。当两个或者多个子集群(subgroups)合并成一个的时候,集群中的成员会收到MergeView message。如果需要在子集群合并时处理子集群状态的合并,那么通常需要在单独的线程里执行耗时的操作。
- SuspectEvent 当集群中的某个成员被怀疑崩溃时,集群中的其它成员会收到SuspectEvent message。通过调用SuspectEvent.getMember()可以得到可疑成员的地址。在收到这个消息后,通常还会收到view message。
- BlockEvent 当收到BlockEvent message后,实例应该停止发送消息,然后应该调用Channel.blockOk()方法(目前JChannel.blockOk()方法是一个空方法)确认已经停止发送消息。当Channel.blockOk()方法调用完毕之后,所有发送消息的线程都会被阻塞直到FLUSH协议解除阻塞。为了接收BlockEvent message,需要设置Channel.BLOCK属性为true。
- UnblockEvent 当收到UnblockEvent message后,实例可以继续发送消息。
- GetStateEvent 当收到GetStateEvent message后,实例应该保存当前的状态,并将当前状态的一份拷贝作为参数调用Channel.returnState()方法,然后JGroups会将这个状态返回给请求状态的实例。为了接收GetStateEvent message,需要在协议栈中配置pbcast.STATE_TRANSFER协议。
- StreamingGetStateEvent当收到StreamingGetStateEvent message后,实例应该通过StreamingGetStateEvent.getArg()返回的输出流返回状态。为了接收StreamingGetStateEvent message,需要在协议栈中配置pbcast.STREAMING_STATE_TRANSFER协议。
- SetStateEvent当收到SetStateEvent message后,实例应该通过SetStateEvent.getArg()返回的字节数组取得状态。
- StreamingSetStateEvent当收到StreamingSetStateEvent message后,实例应该通过StreamingSetStateEvent.getArg()返回的输入流取得状态。为了接收StreamingSetStateEvent message,需要在协议栈中配置pbcast.STREAMING_STATE_TRANSFER协议。
以下是个使用pull方式接收消息的例子:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.jgroups.BlockEvent; import org.jgroups.Channel; import org.jgroups.GetStateEvent; import org.jgroups.JChannel; import org.jgroups.Message; import org.jgroups.SetStateEvent; import org.jgroups.UnblockEvent; import org.jgroups.View; import org.jgroups.util.Util; public class PollStyleReceiver implements Runnable { // private JChannel channel; private Map<String, String> state = new HashMap<String, String>(); private String properties = "UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=32):" + "PING(timeout=3000;num_initial_members=6):" + "FD(timeout=5000):" + "VERIFY_SUSPECT(timeout=1500):" + "pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):" + "UNICAST(timeout=300,600,1200):" + "FRAG:" + "pbcast.GMS(join_timeout=5000;shun=false;print_local_addr=true):" + "pbcast.STATE_TRANSFER:" + "pbcast.FLUSH"; public void start() throws Exception { // channel = new JChannel(properties); channel.connect("PollStyleReceiver"); channel.setOpt(Channel.BLOCK, Boolean.TRUE); channel.getState(null, 10000); new Thread(this).start(); sendMessage(); channel.close(); } @SuppressWarnings({ "unchecked", "deprecation" }) public void run() { while(true) { try { Object obj = channel.receive(0); if(obj instanceof Message) { System.out.println("received a regular message: " + (Message)obj); String s = (String)((Message)obj).getObject(); String key = s.substring(0, s.indexOf("=")); String value = s.substring(s.indexOf("=") + 1); state.put(key, value); } else if(obj instanceof View) { System.out.println("received a View message: " + (View)obj); } else if(obj instanceof BlockEvent) { System.out.println("received a BlockEvent message: " + (BlockEvent)obj); channel.blockOk(); } else if(obj instanceof UnblockEvent) { System.out.println("received a UnblockEvent message: " + (UnblockEvent)obj); } else if(obj instanceof GetStateEvent) { System.out.println("received a GetStateEvent message: " + (GetStateEvent)obj); channel.returnState(Util.objectToByteBuffer(copyState(state))); } else if(obj instanceof SetStateEvent) { System.out.println("received a SetStateEvent message: " + (SetStateEvent)obj); this.state = (Map<String, String>)Util.objectFromByteBuffer(((SetStateEvent)obj).getArg()); System.out.println("current state: " + printState(this.state)); } else { System.out.println(obj); } } catch(Exception e) { e.printStackTrace(); break; } } } private void sendMessage() throws Exception { boolean succeed = false; BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(System.in)); while(true) { System.out.print("> "); System.out.flush(); String line = br.readLine(); if(line != null && line.equals("exit")) { break; } else if(line.indexOf("=") > 0 || line.indexOf("=") == line.length() - 1){ Message msg = new Message(null, null, line); channel.send(msg); } else { System.out.println("invalid input: " + line); } } succeed = true; } finally { if(br != null) { try { br.close(); } catch (Exception e) { if(succeed) { throw e; } } } } } private Map<String, String> copyState(Map<String, String> s) { Map<String, String> m = new HashMap<String, String>(); for(String key : s.keySet()) { m.put(key, s.get(key)); } return m; } private String printState(Map<String, String> s) { StringBuffer sb = new StringBuffer(); sb.append("["); for(Iterator<String> iter = s.keySet().iterator(); iter.hasNext(); ) { String key = iter.next(); sb.append(key).append("="); sb.append(s.get(key)); if(iter.hasNext()) { sb.append(", "); } } sb.append("]"); return sb.toString(); } public static void main(String args[]) throws Exception { new PollStyleReceiver().start(); } }
程序启动后,程序会将在命令行键入键值对(例如key1=value1)保存到HashMap中。并允许在不同的实例间传递状态。
除了以poll的方式接收消息外,JGroups也支持以push的方式处理消息。通过向JChannel注册Receiver,允许程序以回调的方式处理消息,而不必启动额外的线程来接收消息,同时JGroups在内部也不用使用无界队列来保存消息。一下是个使用push方式处理消息的例子:
JChannel ch = new JChannel(); ch.setReceiver(new ExtendedReceiverAdapter() { public void receive(Message msg) { System.out.println("received message " + msg); } public void viewAccepted(View new_view) { System.out.println("received view " + new_view); } }); ch.connect("bla");
2.2.6 State transfer
JGroups支持在集群中维护和传递状态(state),例如web server的Http Sessions等。集群中的某个实例可以通过JChannel.send()方法发送消息,从而把对状态的修改同步到集群的其它实例中。当一个新的实例加入到集群后,可以调用JChannel.getState()方法向集群中的某个实例(缺省是coordinator)请求获得当前的状态。需要注意的是,JChannel.getState()方法返回的是boolean类型。如果该实例是集群中的第一个实例,那么该方法返回false(也就是说目前没有状态),否则返回true。在接下来JChannel.receive()方法的返回值中会包含SetStateEvent message,或者通过MembershipListener.setState()方法获得状态。JChannel.getState()方法不直接返回状态的原因是,如果JChannel的消息队列中还有未被处理的消息,那么让JChannel.getState()直接返回状态,会破坏消息接收的FIFO顺序保证,传递的状态也会不正确。
假设某个集群中包含A、B 和C三个成员,当D加入到集群的时候,如果D调用了JChannel.getState(),那么会发生以下的调用序列:
- D 调用 JChannel.getState()方法。假设状态从集群中的A成员取得。
- A 收到GetStateEvent message或者A注册的Receiver的getState() 方法被调用。A返回了当前状态。
- D 调用 JChannel.getState()方法返回,返回值是true。
- D 收到SetStateEvent message或者D注册的Receiver的setState()方法被调用。D取得状态。
2.2.5节的例子中包含了状态传递相关的代码,需要注意的是,在调用JChannel.returnState()方法的时候,为了防止在状态被通过网络发送前,程序的其它地方对状态进行了修改(比如接收到新的消息并更新状态),需要传递当前状态的一份拷贝。
除了通过处理GetStateEvent 和 SetStateEvent消息来传递状态之外,JGroups也支持通过Reciever传递状态,例如在第一章中演示的例子。
JGroups支持传递部分状态和以流的形式传递状态,详细内容可以参考JGroups Manual。
发表评论
-
Understanding the Hash Array Mapped Trie
2012-03-30 10:36 0mark -
A Hierarchical CLH Queue Lock
2012-01-14 19:01 2150A Hierarchical CLH Queue Lock ( ... -
Inside AbstractQueuedSynchronizer (4)
2012-01-08 17:06 3521Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (3)
2012-01-07 23:37 4734Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (2)
2012-01-07 17:54 6367Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (1)
2012-01-06 11:04 7949Inside AbstractQueuedSynchroniz ... -
Code Optimization
2011-10-14 00:11 1608当前开发人员在进行编码的时候,可能很少关注纯粹代码级别的优化了 ... -
Distributed Lock
2011-08-02 22:02 92111 Overview 在分布式系统中,通常会 ... -
What's New on Java 7 Phaser
2011-07-29 10:15 82751 Overview Java 7的并 ... -
Sequantial Lock in Java
2011-06-07 17:00 22161 Overview Linux内核中常见的同步机 ... -
Feature or issue?
2011-04-26 22:23 121以下代码中,为何CglibTest.intercept ... -
Bloom Filter
2010-10-19 00:41 50741 Overview Bloom filt ... -
Inside java.lang.Enum
2010-08-04 15:40 64771 Introduction to enum J ... -
Open Addressing
2010-07-07 17:59 34591 Overview Open addressi ... -
JLine
2010-06-17 09:11 11010Overview JLine 是一个用来处理控 ... -
ID Generator
2010-06-14 14:45 1677关于ID Generator,想 ... -
inotify-java
2009-07-22 22:58 83011 Overview 最近公 ... -
Perf4J
2009-06-11 23:13 84881 Overview Perf4j是一个用于计算 ... -
Progress Estimator
2009-02-22 19:37 1534Jakarta Commons Cookbook这本书 ... -
jManage
2008-12-22 00:40 39581 Overview 由于项目需要, 笔者开发了一个 ...
相关推荐
此文档主要针对JGroups 2.X版本的官方帮助文档进行详细解读,旨在帮助开发者深入理解并有效地利用JGroups。 一、JGroups简介 JGroups的核心目标是确保在分布式环境中数据的一致性。它提供了一套完整的工具,用于...
JavaEE源代码 jgroups-2.2.8JavaEE源代码 jgroups-2.2.8JavaEE源代码 jgroups-2.2.8JavaEE源代码 jgroups-2.2.8JavaEE源代码 jgroups-2.2.8JavaEE源代码 jgroups-2.2.8JavaEE源代码 jgroups-2.2.8JavaEE源代码 ...
2. 配置Ehcache的`ehcache.xml`,设置`distributed`为`true`启用分布式缓存,并指定Jgroups配置文件的位置。 3. 在代码中初始化Ehcache,确保使用的是集群配置。 测试集群配置,可以启动多台虚拟机或实际的服务器,...
### JGroups教程:深入理解与应用 #### 一、安装JGroups JGroups是一款高性能、高可用性的集群通信中间件,适用于构建分布式系统。本文档将详细介绍如何安装配置JGroups,并编写一个简单的应用来演示其主要功能。 ...
JGroups集群技术概述 JGroups是一个用于建立可靠的组播通信的工具包,它提供了灵活的、可定制的协议栈,以满足不同的需求。JGroups支持多种传输协议,包括UDP、TCP和JMS等。在JGroups中,消息传输可以保证可靠性,...
jgroups-raft 项目是 JGroups 框架对 Raft 的实现。Maven:<groupId>org.jgroups <artifactId>jgroups-raft <version>0.2</version>Raft 是一个容易理解的共识算法。在容错和性能方面它相当于 Paxos(Google 的一致...
jgroups-2.2.7.jar jgroups-2.2.7.jar
《深入解析JGroups开源框架:基于belaban-JGroups-19d7183源代码》 JGroups是一个用于构建高可用性集群的Java框架,它提供了可靠的消息传递、组成员管理和故障检测等功能,广泛应用于分布式系统中。本文将基于bela...
jgroups.part1
2)组成员加入和离开组 3)成员关系的自动侦测并通知成员的加入,离开和丢失(原文是crashed,大意就是说没有通知的离开吧) 4)侦测并删除丢失的成员 5)发送和接收成员到组的消息(点到多点) 6)发送和接收成员...
Jgroups 是一种基于 IP 多播的可靠的组播中间件,UNICAST3 协议是 Jgroups 中的一种单播协议,旨在保持单播和 UNICAST2 的正面特征,而修正负面特征。 UNICAST3 协议的主要特点是: * 提供正确的连接管理(使用...
《JGroups:构建高效可靠的组通信系统》 JGroups是一个用Java编程语言编写的开源库,专注于实现基于IP组播的高效、可配置的组通信协议栈。它为分布式系统提供了一种健壮且灵活的方式来实现节点间的通信,是构建大...
jgroups.part2
### 关于JGroups 2.5教程:安装与开发简易应用程序 #### 安装与配置JGroups **JGroups**是一款高性能、可扩展且高度可靠的群集通信库,旨在为分布式系统提供消息传递功能。本教程将深入探讨如何安装配置JGroups,...
Java多播通讯框架JGroups是Java开发者用于构建高可用、高性能和可伸缩的集群通信系统的重要工具。它提供了一套全面的协议栈,能够处理网络中的节点发现、消息传递、故障检测和恢复等问题,从而使得开发分布式应用变...
JGroups - A Framework for Group Communication in Java ======================================================== March 3, 1998 Bela Ban 4114 Upson Hall Cornell University Ithaca, NY 14853 bba@...
JGroups是一个开源的纯java编写的可靠的群组通讯工具。其是一个可靠的组播通讯工具集(需要说明的是,这并不是说必须要使用IP Multicast,JGroups也可以使用TCP来实现)。其工作模式基于IP多播,但可以在可靠性和群组...
2. 消息处理: 消息到达接收端后,JGROUPS会进行一系列处理: - **接收**:底层网络层接收到数据包,然后将其传递给上一层的协议进行解析。 - **解封装**:协议栈逆序执行,每个协议层对数据包进行解封,恢复...
jgroups.part3