一、 测试内容:
1. 消息持久订阅者在运行过程中死机之后再次重启,是否可以收到之前属于自己应该消费的消息但是由于死机尚未消费的消息。
2. 位于 A 机器上的名为 Durable_Subscriber 的消息持久订阅者由于某种原因导致永久性死机,此时启动 B 机器上的名为 Durable_Subscriber 的消息持久订阅者,测试是否此订阅者是否可以继续接管原来A 上的订阅者的所有工作。
二、 测试程序:
1. 针对测试内容 1 :
1.1 测试程序
- public class MyTopicPublisher {
- static final String CLIENT_ID = "lichaopeng";
- static final String CONN_FACTORY = "my_conn_factory";
- static final String TOPIC_NAME = "my_topic";
- static final String SUBSCRIBER_NAME = "Durable_Subscriber";
- public static void main(String[] args) throws NamingException,
- JMSException, InterruptedException {
- InitialContext cntx = new InitialContext();
- TopicConnectionFactory connFactory = (TopicConnectionFactory) cntx
- .lookup(CONN_FACTORY);
- Topic topic = (Topic) cntx.lookup(TOPIC_NAME);
- TopicConnection conn = connFactory.createTopicConnection();
- TopicSession session = conn.createTopicSession(false,
- TopicSession.CLIENT_ACKNOWLEDGE);
- TopicPublisher publisher = session.createPublisher(topic);
- conn.start();
- int count = 0;
- while (++count <= 10) {
- String text = "TextMessage" + count;
- TextMessage msg = session.createTextMessage(text);
- publisher.publish(msg);
- System.out.println("publisher message:" + text);
- Thread.sleep(5 * 1000);
- }
- }
- }
- public class MyTopicSubsciber implements MessageListener {
- public MyTopicSubsciber() throws NamingException, JMSException {
- InitialContext cntx = new InitialContext();
- TopicConnectionFactory connFactory = (TopicConnectionFactory) cntx
- .lookup(MyTopicPublisher.CONN_FACTORY);
- Topic topic = (Topic) cntx.lookup(MyTopicPublisher.TOPIC_NAME);
- TopicConnection conn = connFactory.createTopicConnection();
- conn.setClientID(MyTopicPublisher.CLIENT_ID);
- TopicSession session = conn.createTopicSession(false,
- TopicSession.CLIENT_ACKNOWLEDGE);
- TopicSubscriber subscriber = session.createDurableSubscriber(topic,
- MyTopicPublisher.SUBSCRIBER_NAME);
- subscriber.setMessageListener(this);
- conn.start();
- }
- public void onMessage(Message arg0) {
- TextMessage msg = (TextMessage) arg0;
- try {
- System.out.println(msg.getText());
- arg0.acknowledge();
- Thread.sleep(8 * 1000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) throws NamingException, JMSException {
- new MyTopicSubsciber();
- }
- }
1.2 测试过程:
首先启动 MyTopicSubsciber ,然后启动 MyTopicPublisher 。
在 MyTopicPublisher 发送了 4 条消息之后,此时 MyTopicSubsciber 刚刚消费了 2 条消息。
此时关闭 MyTopicSubsciber ,而 MyTopicPublisher 继续运行。
然后重启 MyTopicSubsciber , MyTopicSubsciber 接收到了所有之前未消费的消息。
1.3 测试结论:消息持久订阅者在运行过程中死机之后再次重启,可以收到之前属于自己应该消费的消息但是由于死机尚未消费的消息
2. 针对测试内容 2 :
2.1 测试程序:同上
2.2 测试过程:
首先启动 A 上的 MyTopicSubsciber ,然后启动 A 上的 MyTopicPublisher 。
在 MyTopicPublisher 发送了 4 条消息之后,此时 A 上的 MyTopicSubsciber 刚刚消费了 2 条消息。
此时 A 上 MyTopicSubsciber ,而 MyTopicPublisher 继续运行。
启动 B 上的 MyTopicSubsciber , B 上的 MyTopicSubsciber 接收到了所有之前未消费的消息。
2.3 测试结论:位于 A 机器上的名为 Durable_Subscriber 的消息持久订阅者由于某种原因导致永久性死机,此时启动 B 机器上的名为 Durable_Subscriber 的消息持久订阅者,此订阅者可以继续接管原来 A 上的订阅者的所有工作。
三、 备注:
1. 为了更精细的控制整个流程,建议使用 CLIENT_ACKNOWLEDGE 的方式有客户端自己决定应答的时机。
2. 取消订阅的方式:
- public class Unsubscriber {
- public Unsubscriber() throws NamingException, JMSException {
- InitialContext cntx = new InitialContext();
- TopicConnectionFactory connFactory = (TopicConnectionFactory) cntx
- .lookup(MyTopicPublisher.CONN_FACTORY);
- TopicConnection conn = connFactory.createTopicConnection();
- conn.setClientID(MyTopicPublisher.CLIENT_ID);
- TopicSession session = conn.createTopicSession(false,
- TopicSession.CLIENT_ACKNOWLEDGE);
- conn.start();
- session.unsubscribe(MyTopicPublisher.SUBSCRIBER_NAME);
- conn.close();
- }
- public static void main(String[] args) throws NamingException, JMSException {
- new Unsubscriber();
- }
- }
3. JNDI 配置:
- ## do not modify the following please
- java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
- java.naming.factory.url.pkgs=org.jboss.naming;org.jnp.interfaces
- java.naming.security.principal=system
- java.naming.provider.url=tcp://192.168.1.69:61616
- jnp.disableDiscovery=true
- java.naming.security.credentials=manager
- connectionFactoryNames=my_conn_factory
- topic.my_topic=my_topic