如何延迟JMS消息发送?

时间:2014-01-24 16:25:35

标签: java java-ee jms

如何延迟JMS消息发送或进行不确定时间?

我正在使用Weblogic,如你所知,在JMS发送之后,接收器将异步处理消息,但是,此时或有时外部资源还没有为接收器做好准备,因此,我想要一些检查逻辑延迟发送或处理消息。我想例如:我将消息放入待处理队列然后经常检查资源可用性,一旦发送或继续消息?

大家都知道Weblogic是支持这个还是如何实现它?

5 个答案:

答案 0 :(得分:1)

您绝对可以在JMS中执行此操作,只需使用本地队列来存储消息;当接收器可用时发送到远程队列。

选项1(理想,安全)

1)首先,在WebLogic中创建一个JMS服务器LocalJMSServer

2)确保仅将此资源定位到本地WebLogic实例。

3)为tempQueue创建一个队列LocalJMSServer

4)您的应用程序始终向tempQueue发送消息。由于该队列是本地的,所以消息只是位于队列中,并且它们也是持久的,这在服务器崩溃的情况下很好。

5)您需要在WebLogic中使用单独的JMSServer配置来托管remoteQueue,因为该队列将定位到远程WebLogic实例。

6)您的应用程序会定期检查远程接收器的可用性:

   if( receiverIsAvailable()){
    ...
   }

...当接收者可用时,将来自tempQueue的消息出列并发送到remoteQueue ...

Queue tempQueue = (Queue) ctx.lookup("tempQueue");
QueueSession queueLocalSession = 
  queueConn.createQueueSession(false,
     Session.CLIENT_ACKNOWLEDGE);  
QueueReceiver queueReceiver = queueLocalSession.createReceiver(tempQueue);
TextMessage localMessage = (TextMessage) queueReceiver.receive();

//send to remote queue
Queue remoteQueue = (Queue) ctx.lookup("remoteQueue");
QueueSender queueSender = queueRemoteSession.createSender(remoteQueue);
Message newMessage = queueRemoteSession.createTextMessage(
  localMessage.getText());
queueSender.send( newMessage);

//now acknowledge the message since we safely sent to remoteQueue
localMessage.acknowledge(); 

我喜欢这种方法,因为它完全是交易性的;如果出现任何问题,只要您使用PERSISTENT模式,就不会丢失消息。此外,从tempQueue提取消息时,必须使用同步接收器(如上所述),因为它会立即处理来自本地队列的消息,所以不能使用onMessage()

选项2(更简单,更安全)

您还可以使用内存中队列(而不是JMS)在本地存储消息内容:

ArrayBlockingQueue queue = new ArrayBlockingQueue<String>();
queue.add(messageContents1);
queue.add(messageContents2);
...

您的应用程序检查接收方的资源可用性,如果可用,只需出列并立即发送真实的JMS消息:

if( receiverIsAvailable()){
   while(!queue.isEmpty()){
      Message message = session.createTextMessage();
      message.setText(queue.take());
      queueSender.send(message);
   }
}

这种方法的问题是存储在queue中的消息驻留在内存中;如果发件人崩溃,你将失去这些信息。

希望它有所帮助!

答案 1 :(得分:1)

通常,为了延迟接收消息,直到资源准备就绪,不会调用connection.start()方法。这是逻辑:

  1. 接收器启动并建立连接并设置所有JMS资源。
  2. 不调用connection.start()。
  3. 等待其他资源初始化
  4. 使用connection.start()
  5. 启动JM连接

    您甚至可以使用此方法暂停消息侦听器接收的消息。这种技术在使用JMS的GUI工具中非常常见。

答案 2 :(得分:0)

假设您使用的是Websphere MQ,我认为它不受支持。

JMS 2.0确实支持延迟传递[1]消息,但没有更多信息,很难回答。

[1] https://java.net/projects/jms-spec/pages/JMS20FinalRelease#What_s_new_in_JMS_2.0

答案 3 :(得分:0)

如果外部资源尚未就绪,您可以让接收器阻止。由于接收器处于“忙碌状态”,因此在阻塞时不会再从队列中取出消息。

答案 4 :(得分:0)

您是否查看了WebLogic服务器中配置的JMS对象的交付时间设置?

Oracle WebLogic docs