由于公司项目需要使用JMS来进行远程方法的调用,即使用了Spring提供的实现来完成。结果在并发到300左右时总是会出现“慢速消费者”的异常,查看Spring源代码实现看似每次访问都会新建一个会话。结果造成消费积压在JMS服务器上。只能自己动手,即然是消费者连接太多那就减少消费者吧。在客户端建立一个“响应消息池”来接收远程方法吃应消息,线程发送了调用方法消息之前先在此“响应消息池”注册一下表示需要接收消息然后发送调用的消息。
建立一个MessageConsumer实例,设定为用异步方式接收消费。在接收到消费后根据消息池中是否有注册来决定处理方式。同注后得到一个“消息探针”,里面用到了java.util.concurrent.CountDownLatch来帮助实现。
public class MessageProbe { private Map<String, Serializable> returnValue;
private CountDownLatch latch = new CountDownLatch(1); public Map<String, Serializable> await() throws InterruptedException {
latch.await();
return returnValue;
} public Map<String, Serializable> await(long timeout)
throws InterruptedException, TimeoutException {
boolean noTimeout = false;
noTimeout = latch.await(timeout, TimeUnit.MILLISECONDS);
if (noTimeout) {
return returnValue;
} else {
throw new TimeoutException("Response message timed out.");
}
} public void obtainRetunValue(Map<String, Serializable> value) {
returnValue = value;
latch.countDown();
}
}
客户端线程调用await方法,在远程方法没有返回调用结果之前阻塞。返回结果经由obtainRetunValue方法注入后即结束阻塞。各位看看,这样实现有没有什么问题。
我测试下来,并发到1700都正常。
建立一个MessageConsumer实例,设定为用异步方式接收消费。在接收到消费后根据消息池中是否有注册来决定处理方式。同注后得到一个“消息探针”,里面用到了java.util.concurrent.CountDownLatch来帮助实现。
public class MessageProbe { private Map<String, Serializable> returnValue;
private CountDownLatch latch = new CountDownLatch(1); public Map<String, Serializable> await() throws InterruptedException {
latch.await();
return returnValue;
} public Map<String, Serializable> await(long timeout)
throws InterruptedException, TimeoutException {
boolean noTimeout = false;
noTimeout = latch.await(timeout, TimeUnit.MILLISECONDS);
if (noTimeout) {
return returnValue;
} else {
throw new TimeoutException("Response message timed out.");
}
} public void obtainRetunValue(Map<String, Serializable> value) {
returnValue = value;
latch.countDown();
}
}
客户端线程调用await方法,在远程方法没有返回调用结果之前阻塞。返回结果经由obtainRetunValue方法注入后即结束阻塞。各位看看,这样实现有没有什么问题。
我测试下来,并发到1700都正常。
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货