JGroups (3)

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()方法的定义如下:

public RspList castMessage(Vector dests, Message msg, int mode, long timeout);

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

public Object sendMessage(Message msg, int mode, long timeout) throws TimeoutException;

    以下是个使用MessageDispatcher的例子:

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.jgroups.Channel;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.blocks.GroupRequest;
import org.jgroups.blocks.MessageDispatcher;
import org.jgroups.blocks.RequestHandler;
import org.jgroups.util.RspList;

public class MessageDispatcherTest {
	//
	private Channel channel;
	private MessageDispatcher dispatcher;
	private boolean propagateException = false;

	public void start() throws Exception {
		//
		channel = new JChannel();
		dispatcher = new MessageDispatcher(channel, null, null, new RequestHandler() {

			public Object handle(Message msg) {
				System.out.println("got a message: " + msg);
				if(propagateException) {
					throw new RuntimeException("failed to handle message: " + msg.getObject());
				} else {
					return new String("success");
				}
			}
			
		});
		channel.connect("MessageDispatcherTest");
		
		//
		sendMessage();
		
		//
		channel.close();
		dispatcher.stop();
	}
	
	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, line);
					RspList rl = dispatcher.castMessage(null, msg, GroupRequest.GET_ALL, 0);
					System.out.println("Responses:\n" + rl);
				}
			}
			succeed = true;
		} finally {
			if(br != null) {
				try {
					br.close();
				} catch (Exception e) {
					if(succeed) {
						throw e;
					}
				}
			}
		}
	}

	public static void main(String[] args) {
		try {
			new MessageDispatcherTest().start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

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

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.jgroups.Channel;
import org.jgroups.JChannel;
import org.jgroups.blocks.GroupRequest;
import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.util.RspList;

public class RpcDispatcherTest {
	private Channel channel;
	private RpcDispatcher dispatcher;

	public int print(int number) throws Exception {
		return number * 2;
	}

	public void start() throws Exception {
		channel = new JChannel();
		dispatcher = new RpcDispatcher(channel, null, null, this);
		channel.connect("RpcDispatcherTest");
		
		//
		sendMessage();
		
		//
		channel.close();
		dispatcher.stop();
	}
	
	private void sendMessage() throws Exception {
		boolean succeed = false;
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			while(true) {
				System.out.print("> please input an int value:");
				System.out.flush();
				String line = br.readLine();
				if(line != null && line.equals("exit")) {
					break;
				} else {
					int param = 0;
					try {
						param = Integer.parseInt(line);
					} catch(Exception e) {
						System.out.println("invalid input: " + line);
						continue;
					}
					RspList rl = dispatcher.callRemoteMethods(null, "print", new Object[]{new Integer(param)}, new Class[]{int.class}, GroupRequest.GET_ALL, 0);
					System.out.println("Responses: \n" + rl);
				}
			}
			succeed = true;
		} finally {
			if(br != null) {
				try {
					br.close();
				} catch (Exception e) {
					if(succeed) {
						throw e;
					}
				}
			}
		}
	}

	public static void main(String[] args) {
		try {
			new RpcDispatcherTest().start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

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

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.jgroups.Address;
import org.jgroups.ChannelFactory;
import org.jgroups.JChannelFactory;
import org.jgroups.View;
import org.jgroups.blocks.ReplicatedHashMap;

public class ReplicatedHashMapTest implements ReplicatedHashMap.Notification<String, String> {
	//
	private ReplicatedHashMap<String, String> map;

	public void start() throws Exception {
		ChannelFactory factory = new JChannelFactory();
		map = new ReplicatedHashMap<String, String>("ReplicatedHashMapTest", factory, "udp.xml", false, 10000);
		map.addNotifier(this);

		sendMessage();
		map.stop();
	}

	public void entryRemoved(String key) {
		System.out.println("in entryRemoved(" + key + ")");
	}

	public void entrySet(String key, String value) {
		System.out.println("in entrySet(" + key + "," + value + ")");
	}

	public void contentsSet(Map<String, String> m) {
		System.out.println("in contentsSet(" + printMap(m) + ")");
	}

	public void contentsCleared() {
		System.out.println("in contentsCleared()");
	}

	public void viewChange(View view, Vector<Address> newMembers,
			Vector<Address> oldMembers) {
		System.out.println("in viewChange(" + view + ")");
	}

	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.equals("show")) {
						System.out.println(printMap(map));
					} else if (line.equals("clear")) {
						map.clear();
					} else if (line.startsWith("remove ")) {
						String key = line.substring(line.indexOf(" ") + 1, line.length()).trim();
						map.remove(key);
					} else if (line.startsWith("put ")) {
						line = line.replace("put ", "");
						int index = line.indexOf("=");
						if (index <= 0 || index >= (line.length() - 1)) {
							System.out.println("invalid input");
							continue;
						}
						String key = line.substring(0, index).trim();
						String value = line.substring(index + 1, line.length())
								.trim();
						map.put(key, value);
					} else {
						System.out.println("invalid input: " + line);
						continue;
					}
				}
			}
			succeed = true;
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (Exception e) {
					if (succeed) {
						throw e;
					}
				}
			}
		}
	}

	private String printMap(Map<String, String> m) {
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (Iterator<String> iter = map.keySet().iterator(); iter.hasNext();) {
			String key = iter.next();
			String value = map.get(key);
			sb.append(key).append("=").append(value);
			if (iter.hasNext()) {
				sb.append(",");
			}
		}
		sb.append("]");
		return sb.toString();
	}

	public static void main(String args[]) {
		try {
			new ReplicatedHashMapTest().start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

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

public interface Consumer {
    void handleNotification(Serializable n);
    Serializable getCache();
    void memberJoined(Address mbr);
    void memberLeft(Address mbr);
}

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

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;

import org.jgroups.Address;
import org.jgroups.blocks.NotificationBus;

public class NotificationBusTest implements NotificationBus.Consumer {
	//
	private NotificationBus bus;
	private LinkedList<Serializable> cache;

	public void handleNotification(Serializable n) {
		System.out.println("in handleNotification(" + n + ")");
		if (cache != null) {
			cache.add(n);
		}
	}

	public Serializable getCache() {
		return cache;
	}

	public void memberJoined(Address mbr) {
		System.out.println("in memberJoined(" + mbr + ")");
	}

	public void memberLeft(Address mbr) {
		System.out.println("in memberLeft(" + mbr + ")");
	}

	@SuppressWarnings("unchecked")
	public void start() throws Exception {
		//
		bus = new NotificationBus("NotificationBusTest", null);
		bus.setConsumer(this);
		bus.start();
		cache = (LinkedList<Serializable>) bus.getCacheFromCoordinator(3000, 1);
		if (cache == null) {
			cache = new LinkedList<Serializable>();
		}
		System.out.println(printCache(cache));

		//
		sendNotification();

		//
		bus.stop();
	}

	private void sendNotification() 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 {
					bus.sendNotification(line);
				}
			}
			succeed = true;
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (Exception e) {
					if (succeed) {
						throw e;
					}
				}
			}
		}
	}

	private String printCache(LinkedList<Serializable> c) {
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (Iterator<Serializable> iter = c.iterator(); iter.hasNext();) {
			sb.append(iter.next());
			if (iter.hasNext()) {
				sb.append(",");
			}
		}
		sb.append("]");
		return sb.toString();
	}

	public static void main(String[] args) {
		try {
			new NotificationBusTest().start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
阅读更多

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各路神仙, 大侠帮帮忙....谢谢

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