JGroups (1)

1 Overview
    JGroups是一个用于建立可靠的组播通信的工具包(这里指的组播并不一定是IP Multicast,JGroups同样支持使用TCP作为传输协议)。其中可靠性是指通过适当的配置可以保证:消息在传输的过程中不会丢失;所有的接收者以相同的顺序接受所有的消息;原子性:一个消息要么被所有的接收者接收,要么不被任何一个接收者都接收。目前在JBoss Application Server Clustering,OSCache Clustering,Jetty HTTP session replication,  Tomcat HTTP session replication中都使用了JGroups。

Unreliable Reliable
Unicast UDP TCP
Multicast IP Multicast JGroups

    TCP和UDP是单播(Unicast)协议,也就是说:发送者和每一接收者之间是点对点传输。 如果一个发送者希望向多个接收者传输相同的数据,那么必须相应的复制多份数据。TCP是可靠的传输协议,但UDP不是可靠的,也就是说报文在传输的过程中可能丢失、重复或着乱序,报文的最大尺寸也有限制。IP Multicast可以将消息同时发送到多个接收者。由于IP Multicast是基于UDP的,因此IP Multicast是不可靠的。IP Multicast需要一个特殊的组播地址,它是一组D类IP地址,范围从224.0.0.0 到 239.255.255.255,其中有一部分地址是为特殊的目的保留的。JGroups使用UDP (IP Multicast)、TCP、JMS作为传输协议。JGroups最强大的功能之一是提供了灵活的,可定制的协议栈,以满足不同的需求。例如,如果选择使用IP Multicast作为传输协议,那么为了防止报文丢失和重复,可以在协议栈中添加NAKACK协议;为了保证报文的顺序,可以在协议栈中添加TOTAL协议,以保证FIFO的顺序;为了在组内成员发生变化时得到通知和回调,可以添加Group Membership Service (GMS) 和 FLUSH协议;Failure Detector (FD)协议用于识别组内崩溃的成员;如果新加入的成员希望获得组内其它成员维护的状态,那么可以向协议栈中添加STATE_TRANSFER协议;如果希望对传输的数据进行加密,那么可以使用CRYPT协议等等。

    JGruops的主要功能有:

  • 组的创建和删除。组可以跨越LANs或者WANs。
  • 加入组、主动或者被动(例如当机或者网络故障)离开组。
  • 在组成员改变时,组中其它成员可以得到通知。
  • 向组中的单个或者多个成员发送消息。

    在JGroups中JChannel类提供了主要的API ,用于连接到集群(cluster)、发送和接收消息(Message)和注册listeners等。Message包含消息头(保存地址等信息)和一个字节数组(保存希望传输的数据)。org.jgroups.Address接口及其实现类封装了地址信息,它通常包含IP地址和端口号。连接到集群中的所有实例(instance)被称为一个视图(org.jgroups.View)。通过View.getMembers()可以得到所有实例的地址。实例只有在连接到集群后才能够发送和接收消息。以相同name调用JChannel.connect(String name)方法的所有实例会连接到同一个集群。当实例希望离开集群时,可以调用JChannel.disconnect()方法。当希望释放占有的资源时,可以调用JChannel.close()方法。JChannel.close()方法内部会调用JChannel.disconnect()方法。
    通过调用JChannel.setReceiver()方法可以接收消息和得到View改变的通知。每当有实例加入或者离开集群的时候,viewAccepted(View view)方法会被调用。View.toString()方法会打印出View中所有实例的地址,以及View ID。需要注意的是,每次viewAccepted(View view)方法被调用时,view参数都不同,其View ID也会增长。View内的第一个实例被称为coordinator。Receiver接口上的getState(),setState()方法用于在实例间传递状态。新的实例通过setState()方法获得通过状态,而这个状态是通过调用集群中其它某个实例上的getState()获得的。

    以下是JGruops manual中的一个简单的例子:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;

import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.ReceiverAdapter;
import org.jgroups.View;
import org.jgroups.util.Util;

public class SimpleChat {
	//
	private JChannel channel;
	private List<String> state = new LinkedList<String>();
	private String userName = System.getProperty("user.name", "WhiteSock");
	
	public void start() throws Exception {
		//
		channel = new JChannel();
		channel.setReceiver(new ReceiverAdapter() {
			
			public void receive(Message msg) {
				System.out.println(msg.getSrc() + ": " + msg.getObject());
				
				synchronized(state) {
					state.add((String)msg.getObject());
				}
			}
			
			public void viewAccepted(View view) {
				System.out.println("view accepted: " + view);
			}
			
			public byte[] getState() {
				synchronized(state) {
					try {
						return Util.objectToByteBuffer(state);
					}
					catch(Exception e) {
						e.printStackTrace();
						return null;
					}
				}
			}
			
			@SuppressWarnings("unchecked")
			public void setState(byte[] new_state) {
				try {
					List<String> list=(List<String>)Util.objectFromByteBuffer(new_state);
					synchronized(state) {
						state.clear();
						state.addAll(list);
					}
					System.out.println("received state (" + list.size() + " messages in chat history):");
					for(String str: list) {
						System.out.println(str);
					}
				}
				catch(Exception e) {
					e.printStackTrace();
				}
			}
		});
		channel.connect("ChatCluster");
		channel.getState(null, 10000);
		
		//
		sendMessage();
		
		//
		channel.close();
	}
	
	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 {
					Message msg = new Message(null, null, "[" + userName + "]" + line);
					channel.send(msg);
				}
			}
			succeed = true;
		} finally {
			if(br != null) {
				try {
					br.close();
				} catch (Exception e) {
					if(succeed) {
						throw e;
					}
				}
			}
		}
	}
	
	public static void main(String args[]) throws Exception {
		new SimpleChat().start();
	}
}

    在以上例子中,主线程会阻塞,直到从stdin中读取一行。如果这行是"exit",那么程序退出,否则向集群中发送一个消息。如果集群中某个实例强行退出,那么集群中的其它实例也会得到通知。Message构造函数的第一个参数如果是null,那么意味着消息将被发送到集群内所有的实例。

阅读更多

JGroups 问题请教.........

05-06

用JGROUPS实现负载均衡、数据同步问题(采用TCP方式)。用LOADRUNNER 对它进行压力测试时(如:采用4台压力机),如果是500并发,正常。如果加大并发1000。很快就会DOWN机。出现如下问题。请各位高手指点。。是不是JGroups不支持高并发???急。。。。。。。。。rnrnrnrnrnFull thread dump Java HotSpot(TM) Server VM (11.0-b15 mixed mode):rnrnrn"OOB-241,OOP_NAMxxxxdddE,192.168.0.2:7800" prio=10 tid=0x08e97c00 nid=0x1464 waiting on condition [0x178bb000..0x178bbe30]rn java.lang.Thread.State: WAITING (parking)rn at sun.misc.Unsafe.park(Native Method)rn - parking to wait for <0xb13e0168> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)rn at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)rn at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925)rn at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:358)rn at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)rn at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)rn at java.lang.Thread.run(Thread.java:619)rn"Timer-2,OOP_NAMxxxxdddE,192.168.9.205:7800" daemon prio=10 tid=0x2204a000 nid=0xf9c waiting on condition [0x2249b000..0x2249bf30]rn java.lang.Thread.State: TIMED_WAITING (parking)rn at sun.misc.Unsafe.park(Native Method)rn - parking to wait for <0xb1487208> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)rn at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)rn at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1963)rn at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)rn at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:583)rn at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:576)rn at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)rn at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)rn at java.lang.Thread.run(Thread.java:619)rnrn"ConnectionTable.AcceptorThread,null,192.168.9.205:7800" prio=10 tid=0x21fd5000 nid=0xf9b runnable [0x224bc000..0x224bcdb0]rn java.lang.Thread.State: RUNNABLErn at java.net.PlainSocketImpl.socketAccept(Native Method)rn at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)rn - locked <0xb1491de8> (a java.net.SocksSocketImpl)rn at java.net.ServerSocket.implAccept(ServerSocket.java:453)rn at java.net.ServerSocket.accept(ServerSocket.java:421)rn at org.jgroups.blocks.ConnectionTable.run(ConnectionTable.java:239)rn at java.lang.Thread.run(Thread.java:619)rnrn"DiagnosticsHandler,OOP_NAMxxxxdddE,192.168.9.205:7800" daemon prio=10 tid=0x21fd4800 nid=0xf9a runnable [0x224dd000..0x224dde30]rn java.lang.Thread.State: RUNNABLErn at java.net.PlainDatagramSocketImpl.receive0(Native Method)rn - locked <0xb1489d88> (a java.net.PlainDatagramSocketImpl)rn at java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:136)rn - locked <0xb1489d88> (a java.net.PlainDatagramSocketImpl)rn at java.net.DatagramSocket.receive(DatagramSocket.java:712)rn - locked <0xb184b338> (a java.net.DatagramPacket)rn - locked <0xb1489d50> (a java.net.MulticastSocket)rn at org.jgroups.protocols.TP$DiagnosticsHandler.run(TP.java:2187)rn at java.lang.Thread.run(Thread.java:619)rnrn"FD_SOCK server socket acceptor,null,null" daemon prio=10 tid=0x08c35c00 nid=0xf99 runnable [0x224fe000..0x224ff0b0]rn java.lang.Thread.State: RUNNABLErn at java.net.PlainSocketImpl.socketAccept(Native Method)rn at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)rn - locked <0xb14d8878> (a java.net.SocksSocketImpl)rn at java.net.ServerSocket.implAccept(ServerSocket.java:453)rn at java.net.ServerSocket.accept(ServerSocket.java:421)rn at org.jgroups.protocols.FD_SOCK$ServerSocketHandler.run(FD_SOCK.java:1016)rn at java.lang.Thread.run(Thread.java:619)rnrnrn"Timer-1" daemon prio=10 tid=0x0877b400 nid=0xf94 in Object.wait() [0x2269b000..0x2269bf30]rn java.lang.Thread.State: TIMED_WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn at java.util.TimerThread.mainLoop(Timer.java:509)rn - locked <0xb184b498> (a java.util.TaskQueue)rn at java.util.TimerThread.run(Timer.java:462)rnrn"MySQL Statement Cancellation Timer" daemon prio=10 tid=0x08db3400 nid=0xf89 in Object.wait() [0x226bc000..0x226bcdb0]rn java.lang.Thread.State: WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn - waiting on <0xb1759610> (a java.util.TaskQueue)rn at java.lang.Object.wait(Object.java:485)rn at java.util.TimerThread.mainLoop(Timer.java:483)rn - locked <0xb1759610> (a java.util.TaskQueue)rn at java.util.TimerThread.run(Timer.java:462)rnrn"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2" daemon prio=10 tid=0x086d7000 nid=0xf88 in Object.wait() [0x226dd000..0x226dde30]rn java.lang.Thread.State: TIMED_WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)rn - locked <0xb14f0c48> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner)rnrn"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1" daemon prio=10 tid=0x08c67400 nid=0xf87 in Object.wait() [0x226fe000..0x226ff0b0]rn java.lang.Thread.State: TIMED_WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)rn - locked <0xb14f0c48> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner)rnrn"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0" daemon prio=10 tid=0x08508800 nid=0xf86 in Object.wait() [0x22a3f000..0x22a3f130]rn java.lang.Thread.State: TIMED_WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)rn - locked <0xb14f0c48> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner)rnrn"Timer-0" daemon prio=10 tid=0x086ce800 nid=0xf85 in Object.wait() [0x23027000..0x23027fb0]rn java.lang.Thread.State: TIMED_WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn at java.util.TimerThread.mainLoop(Timer.java:509)rn - locked <0xb14fd730> (a java.util.TaskQueue)rn at java.util.TimerThread.run(Timer.java:462)rnrn"License Monitior Thread" daemon prio=10 tid=0x22e9fc00 nid=0xf84 waiting on condition [0x2304f000..0x23050030]rn java.lang.Thread.State: TIMED_WAITING (sleeping)rn at java.lang.Thread.sleep(Native Method)rn at cn.com.OOP.cinas.license.LicenseMonitior.run(LicenseMonitior.java:51)rnrn"Low Memory Detector" daemon prio=10 tid=0x082abc00 nid=0xf82 runnable [0x00000000..0x00000000]rn java.lang.Thread.State: RUNNABLErnrn"CompilerThread1" daemon prio=10 tid=0x082aa000 nid=0xf81 waiting on condition [0x00000000..0x23a0a268]rn java.lang.Thread.State: RUNNABLErnrn"CompilerThread0" daemon prio=10 tid=0x082a7400 nid=0xf80 waiting on condition [0x00000000..0x23a8b2e8]rn java.lang.Thread.State: RUNNABLErnrn"Signal Dispatcher" daemon prio=10 tid=0x082a5c00 nid=0xf7f runnable [0x00000000..0x23aacd90]rn java.lang.Thread.State: RUNNABLErnrn"Finalizer" daemon prio=10 tid=0x08283800 nid=0xf7e in Object.wait() [0x23d77000..0x23d78130]rn java.lang.Thread.State: WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn - waiting on <0xb18b44f0> (a java.lang.ref.ReferenceQueue$Lock)rn at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)rn - locked <0xb18b44f0> (a java.lang.ref.ReferenceQueue$Lock)rn at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)rn at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)rnrn"Reference Handler" daemon prio=10 tid=0x08282000 nid=0xf7d in Object.wait() [0x23d98000..0x23d98fb0]rn java.lang.Thread.State: WAITING (on object monitor)rn at java.lang.Object.wait(Native Method)rn - waiting on <0xb14a8c58> (a java.lang.ref.Reference$Lock)rn at java.lang.Object.wait(Object.java:485)rn at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)rn - locked <0xb14a8c58> (a java.lang.ref.Reference$Lock)rnrn"VM Thread" prio=10 tid=0x0827e800 nid=0xf7c runnable rnrn"GC task thread#0 (ParallelGC)" prio=10 tid=0x08190c00 nid=0xf74 runnable rnrn"GC task thread#1 (ParallelGC)" prio=10 tid=0x08192400 nid=0xf75 runnable rnrn"GC task thread#2 (ParallelGC)" prio=10 tid=0x08193800 nid=0xf76 runnable rnrn"GC task thread#3 (ParallelGC)" prio=10 tid=0x08195000 nid=0xf77 runnable rnrn"GC task thread#4 (ParallelGC)" prio=10 tid=0x08196800 nid=0xf78 runnable rnrn"GC task thread#5 (ParallelGC)" prio=10 tid=0x08197c00 nid=0xf79 runnable rnrn"GC task thread#6 (ParallelGC)" prio=10 tid=0x08199400 nid=0xf7a runnable rnrn"GC task thread#7 (ParallelGC)" prio=10 tid=0x0819a800 nid=0xf7b runnable rnrn"VM Periodic Task Thread" prio=10 tid=0x082adc00 nid=0xf83 waiting on condition rnrnJNI global references: 1154rnrnrn

JGroups UDP multicast 救急!

06-11

请教一下大侠有关 JGroups UDP multicast的问题:rnrn1. 发送端和接收端都必须要用JGroups才可以互相通讯吗, 如果发送端用JGroups, 接收端用普通JAVA API, 或者反过来的话, 可以通讯吗?(我测试的结果是不可以通讯, 不知道JGroups是不是像MQ那样, 发送端和接收端都得用它, 还是我测试不正确?)rnrn2. 局域网内接收不到消息: rn在一台机子上, 发送端用 JGroups UDP multicast 发送消息, 如果接收端也在同一台机子上, 则可以接收到消息. 如果发送端放在A机子上, 接收端放在B机子上(A和B都在同一局域网内), 则收不到消息, 为什么呢? (配置文件的内容在下面)rnrn3. 消息丢包/重发的问题:rn在消息发送频率高的情况下, 发送端发送的消息为msg1, msg2, msg3, msg4, msg5, msg6, msg7, msg8, msg9, msg10, msg11, 但是在接收端收到的消息可能为 msg3, msg3, msg3, msg5, msg5, msg7, msg7, msg9, msg9, msg11, msg11. 接收端收到的消息中, 有些重复, 有些丢失, 是不是配置方面的问题呢? rnrnrn配置文件如下:rn[code=XML]rn我把用到的配置文件也贴出来吧(udp.xml): rnrnrnrn rn rn rn rn rn rn rn rn rn rn rn rn rn rn[/code]rnrnrn发送端的主要代码:rn[code=Java]rnrnbyte[] sentBytes = xxxxxxx // 生成发送字节数组的内容, 代码省略.rnrnJChannel channel = new JChannel(new File(PathUtils.find("conf/udp.xml")));rn channel.connect("my_jgroups");rn while (true) rn channel.send(null, sentBytes);rn Thread.sleep(1000); rn rnrn[/code]rnrnrn接收端的主要代码:rn[code=Java]rnrnJChannel channel = new JChannel(new File(PathUtils.find("conf/udp.xml")));rn channel.setReceiver(new ReceiverAdapter() rn @Overridern public void receive(Message message) rn System.out.println("received : " + new String(message.getBuffer()));rn rnrn @Overridern public void viewAccepted(View view1) rn System.out.println("received view : " + view1);rn rn );rnrn channel.connect("my_jgroups");rnrn[/code]rnrnrn各路神仙, 大侠帮帮忙....谢谢

没有更多推荐了,返回首页