当前位置: 首页 > 知识库问答 >
问题:

如何延迟JMS消息发送?

权韬
2023-03-14

如何延迟JMS消息发送或在不确定的时间内继续?

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

大家都知道Weblogic是否支持这一点,或者如何实现它吗?

共有3个答案

楚硕
2023-03-14

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

JMS2.0确实支持消息的延迟传递,但是如果没有更多的信息,就很难回答。

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

龙凯
2023-03-14

通常情况下,为了延迟消息的接收,直到资源准备就绪,连接将中断。未调用start()方法。逻辑如下:

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

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

范浩宕
2023-03-14

您完全可以在JMS中实现这一点,只需使用本地队列来存储消息;当接收器可用时发送到远程队列。

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

2) 确保此资源仅针对本地WebLogic实例。

3)为LocalJMSServer创建一个队列,temQueue

4)您的应用程序总是将消息发送到temQueue。由于该队列是本地的,消息只是放在队列中,并且它们也被持久化,这在服务器崩溃的情况下是很好的。

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

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

   if( receiverIsAvailable()){
    ...
   }

...当接收器可用时,从temQueue中取出消息并将其发送到Remote teQueue...

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(); 

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

您还可以使用内存队列(而不是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);
   }
}

这种方法的问题是存储在队列中的消息驻留在内存中;如果发送方崩溃,您将丢失这些消息。

希望有帮助!

 类似资料:
  • 此应用程序收到 但是,当不存在web套接字会话,并且JMSProducer将消息发送到QueueSenderSessionBean中的目标“jms/notificationQueue”时,消息会立即在NotificationEndpoint中使用。这不是我的意图。 我的目的是让队列保留消息,直到用户连接到NotificationEndpoint。如果用户没有连接到NotificationEndpo

  • spring XML中的jmsTemplate定义: 有人对问题有什么建议吗/关于如何实现延迟消息传递的其他想法?谢了!

  • 主要内容:1 load加载延迟消息数据,1.1 parseDelayLevel解析延迟等级,2 start启动调度消息服务,3 DeliverDelayedMessageTimerTask投递延迟消息任务,3.1 executeOnTimeup执行延迟消息投递,3.2 scheduleNextTimerTask下一个调度任务,3.3 correctDeliverTimestamp校验投递时间,3.4 messageTimeup恢复正常消息,,基于RocketMQ release-4.9.3,深入

  • 我正在使用Spring Kafka1.0.3来消费kafka消息。Kafka的2个主题,每个主题有1个分区。在java代码中,有2@KafKalistener来消费每个主题消息。ConcurrentKafkaListenerContainerFactory的并发设置为1。但消息有时会延迟20秒以上。 有人知道为什么吗? 添加调试日志,并且延迟不是每次都可以,有时也可以:

  • 如何使用Apache Kafka生成/使用延迟消息?标准的Kafka(和Java的kafka-client)功能似乎没有这个特性。我知道我自己可以用标准的等待/通知机制来实现它,但是它看起来不是很可靠,所以任何建议和好的实践都很感谢。 找到相关问题,但没有帮助。正如我所看到的:Kafka基于从文件系统的顺序读取,并且只能用于直接读取主题,保持消息的顺序。我说的对吗?