如何延迟 JMS 消息发送?

3
如何延迟JMS消息发送或处理不确定的时间? 我正在使用Weblogic,众所周知,在JMS发送后,接收器将异步处理消息,但是此时或有时外部资源尚未准备好接收器,因此,我希望有一些检查逻辑来延迟发送或处理消息。我猜想例如:将消息放入挂起队列中,然后经常检查资源可用性,一旦准备就发送或处理消息?每个人都知道Weblogic是否支持此功能或如何实现吗?

我在Weblogic中没有听说过这样的东西。听起来你将不得不自己实现一个“等待”队列。 - Eugene
JMS的目的是将消息放入队列中,以便接收者异步处理。那么,请问您所说的“接收者必须立即执行操作”是什么意思? - crnlx
谢谢回复,我刚刚修改了问题,使其更加清晰明了。 - C.c
5个回答

1
你可以在JMS中做到这一点,只需使用本地队列存储消息; 当接收方可用时,发送到远程队列。
选项1(理想,安全):
1)首先,在WebLogic中创建一个JMS服务器,LocalJMSServer。
2)确保将此资源仅针对本地WebLogic实例进行定位。
3)为LocalJMSServer创建一个名为tempQueue的队列。
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

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

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

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


谢谢,你能告诉我如何暂停接收消息吗? - C.c
Connection.start()和Connection.stop()可以在消息监听器线程之外调用。在程序停止之前调用connection.stop()是很常见的。如果想要在任何时间点暂停接收消息,可以调用connection.stop()。 - Neeraj Krishna

0

0

如果外部资源没有准备好,您可以让接收器进入阻塞状态。由于接收器处于“忙碌”状态,因此在其被阻塞期间不会从队列中拉取更多的消息。


0
你有没有查看过在WebLogic服务器中配置的JMS对象的交付时间设置? Oracle WebLogic文档

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接