1:在weblogic cluster环境中,配置一个Distributed Queue, 它的QueueMember分布于cluster中不同managed server上的JMS Server上。JMS采用filestore方式存储消息。如果运行过程中,某一个managed server发生宕机的话,它的JMS Server上的消息在重起前,能不能被客户端consume掉?
要回答这个问题,首先我们先看一下Distributed Queue的概念。所谓distributed queue, 顾名思义,分布式队列。它实际上是个逻辑Queue, 管理着一堆物理Queue。这些物理Queue对于客户端是透明的,即客户端发送、接收消息的时候,他们无法辨别这个消息到底发到哪个物理Queue,消息从哪个物理Queue接收到的。客户端看到的只是一个DQ,对于客户端已经足够了,至于发到哪,从哪接收,这些由Weblogic帮你去做。好了,回到这个问题,客户做JMSServer配置的时候,filestore不能共享文件,即一个filestore对应一个物理文件(这些文件可以通过ScanStore查看),而且jms server关联的filestore只能和它自己部署在同一managed server上。filestore只能部署到某个managed server上,其实无论是filestore,还是jdbcstore,都不能部署到cluster上。由于store不能部署到cluster上,jms server于是不能共享store(共享store会涉及到IO同步问题、事务问题)。当运行过程中,某个managed server宕机的话,在它启动之前,它上面filestore是不可用的,即filestore中的message不可读,message当然也就不能被其他客户端消费了。
题外话:测试中,我让两个JMSServer使用不同的jdbc store, 但这两个jdbc store指向同一数据源。虽然active changes的时候,console不会看到什么错误,当log文件中会记录store.open()相关的错误,原因就在于两个不同的jms server使用了同一张叫做WLStore的表。第一个store用了这个表,第二个就不能使用了。重起这两个managed server, 后启动的那个不会变成running mode, 它会一直处于admin状态(jms service无法启动)。
2:message consume的时候,会不会做load balance?
不会!客户端做message send的时候,weblogic server会根据DQ的load banlance policy做load balance,即每调用一次send,都会做一次load balance,这样消息会在物理Queue之间均分(至于哪些物理Queue会参与均分,这跟loadbalance、serverAffinity设定有关),另外,当所有QueueMember中,只有某个Queue有consumer的时候,那么所有消息都会发送到这个QueueMember,然后被消费。客户端consume的时候,consumer被创建的时候,weblogic会分配一个物理Queue给它,即该consumer只能从这个物理Queue上接受消息。当然consumer被重新创建的时候,它们会粘连到不同的物理Queue上。
3:Consumer粘连的物理Queue所在的server宕机,不重起consumer的话,它能不能继续收到消息? 物理Queue所在server重启之后,它能不能接收?
两种情况都不能!这种问题典型场景就是message listener或message driven bean,问题2中我们提到,consumer创建的时候,它会粘连到某个物理Queue上,如果物理Queue所在的managed server宕机了,Queue就不会有消息进来(内存中都不存在这个物理Queue),当然这个consumer就不会收到消息了。对于第二种情况,即managed server重起之后,这个consumer如果不重起(或重建consumer)的话,它依然不会收到消息。对于这个问题,我们首先了解一下listener的机制: listener是客户端通过setMessageListener设定到consumer中的,这个设定会驻留在服务器端,当服务器端发现对应Queue上有消息的时候,他们通过callback机制,把消息传递到客户端的listener,listener的onMessage()被触发,执行相应的逻辑。因为listener信息是保存在服务器端的,当managed server宕机并重起的时候,它不会recover listener信息,即即使consumer对应的物理Queue上有消息进来的时候,managed server上的jms server也不会通过listener callback把消息deliver给consumer,因为它根本不知道这个consumer的存在。
对于第二中情况,我觉得这应该是weblogic设计的问题,它不能让客户端感知到managed server的crash,客户端如果不知道后端发生什么的话,只能傻傻的等着。其实weblogic应该可以通过peerGone event抛出exception,客户端可以去处理这个异常,重建consumer还是退出,由客户端自己处理。这样做感觉会更好些吧!
更新!!!!!!!
对于最后关于异常处理的问题,实际上weblogic(也包含其他AppServer Vendor)提供了异常监听功能,这是JMS规范的要求。具体的API是connection.setExceptionListener(JMSException e), 对于这个API,客户端程序要做的就是,提供一个实现JMSExceptionListener的listener类,然后在connection创建完成后,将这个listener实例注入到这个新建的connection上,这样这个连接发生JMSException的时候,ExceptionListener的onException()会被触发,客户可以在onException()中定义异常处理逻辑。下面是个exception listener的例子,
1 import javax.jms.ExceptionListener;
2 import javax.jms.JMSException;
3
4 public class TestExceptionListener implements ExceptionListener {
5
6 public void onException(JMSException e){
7 System.out.println("jms exception is encountered, and onException is triggered!");
8 e.printStackTrace();
9 }
10
11 }
对于这个listener,我们可以将底层的JMSException输出,如果runtime过程中,对端managed server发生crash,我们可以看到如下的exception,
weblogic.jms.common.LostServerException: java.lang.Exception: weblogic.rjvm.PeerGoneException: ;
nested exception is:
weblogic.utils.net.SocketResetException
at weblogic.jms.client.JMSConnection.dispatcherPeerGone(JMSConnection.java:1348)
at weblogic.messaging.dispatcher.DispatcherWrapperState.run(DispatcherWrapperState.java:571)
at weblogic.messaging.dispatcher.DispatcherWrapperState.timerExpired(DispatcherWrapperState.java:496)
at weblogic.timers.internal.TimerImpl.run(TimerImpl.java:265)
at weblogic.work.ExecuteRequestAdapter.execute(ExecuteRequestAdapter.java:21)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:145)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:117)
Caused by: java.lang.Exception: weblogic.rjvm.PeerGoneException: ; nested except
ion is:
weblogic.utils.net.SocketResetException
at weblogic.messaging.dispatcher.DispatcherWrapperState.onDisconnect(DispatcherWrapperState.java:276)
at weblogic.rjvm.RJVMImpl$DisconnectEventDeliverer.run(RJVMImpl.java:1603)
... 3 more
Caused by: weblogic.rjvm.PeerGoneException: ; nested exception is:
weblogic.utils.net.SocketResetException
at weblogic.rjvm.RJVMImpl.gotExceptionReceiving(RJVMImpl.java:941)
at weblogic.rjvm.ConnectionManager.gotExceptionReceiving(ConnectionManager.java:1025)
at weblogic.rjvm.MsgAbbrevJVMConnection.gotExceptionReceiving(MsgAbbrevJVMConnection.java:452)
at weblogic.rjvm.t3.MuxableSocketT3.hasException(MuxableSocketT3.java:373)
at weblogic.socket.SocketMuxer.deliverExceptionAndCleanup(SocketMuxer.java:739)
at weblogic.socket.SocketMuxer.deliverHasException(SocketMuxer.java:692)
at weblogic.socket.SocketMuxer.readReadySocketOnce(SocketMuxer.java:875)
at weblogic.socket.SocketMuxer.readReadySocket(SocketMuxer.java:792)
at weblogic.socket.JavaSocketMuxer.processSockets(JavaSocketMuxer.java:283)
at weblogic.socket.SocketReaderRequest.run(SocketReaderRequest.java:29)
... 3 more
Caused by: weblogic.utils.net.SocketResetException
at weblogic.socket.SocketMuxer.readReadySocketOnce(SocketMuxer.java:863)
... 6 more
posted on 2009-04-22 09:35
走走停停又三年 阅读(4158)
评论(3) 编辑 收藏 所属分类:
Weblogic