简体   繁体   English

如何延迟JMS消息发送?

[英]How do I delay JMS Message sending?

How do I delay JMS Message sending or proceed uncertain time? 如何延迟JMS消息发送或进行不确定的时间?

I am using Weblogic, as you know, after JMS sending, the receiver will process the message asynchronously, but, at this time or sometimes the external resource are not ready for the receiver, therefore, I want to have some check logic to delay send or process the message. 我正在使用Weblogic,如你所知,在JMS发送之后,接收器将异步处理消息,但是,此时或者有时外部资源还没有为接收器做好准备,因此,我想要一些检查逻辑来延迟发送或处理消息。 I guess for example: I put the message into pending queue then frequently check the resource availability, once it is then send or proceed the message? 我想例如:我将消息放入待处理队列然后经常检查资源可用性,一旦发送或继续消息?

Do everybody know does Weblogic support this or how to implement it? 大家都知道Weblogic是支持这个还是如何实现它?

You can absolutely do this in JMS, just use a local queue for storing the messages; 你绝对可以在JMS中执行此操作,只需使用本地队列来存储消息; send to remote queue when receiver is available. 当接收器可用时发送到远程队列。

Option 1 (Ideal, Safe) 选项1(理想,安全)

1) First, create a JMS Server in WebLogic, LocalJMSServer . 1)首先,在WebLogic, LocalJMSServer创建JMS服务器。

2) Make sure to target this resource only to the local WebLogic instance only. 2)确保仅将此资源仅定位到本地WebLogic实例。

3) Create a queue, tempQueue , for LocalJMSServer . 3)创建一个队列, tempQueue ,用于LocalJMSServer

4) Your application always sends messages to tempQueue . 4)您的应用程序始终向tempQueue发送消息。 Since that queue is local, the messages just sit on the queue, and they are persisted too which is nice in case server crashes. 由于该队列是本地的,因此消息只是位于队列中,并且它们也是持久的,这在服务器崩溃的情况下很好。

5) You'll need a separate JMSServer configuration in WebLogic to host the remoteQueue since that queue will be targeted to a remote WebLogic instance. 5)您需要在WebLogic中使用单独的JMSServer配置来托管remoteQueue因为该队列将定位到远程WebLogic实例。

6) Your application periodically checks the remote receiver for availability: 6)您的应用程序会定期检查远程接收器的可用性:

   if( receiverIsAvailable()){
    ...
   }

...when the receiver is available, dequeue messages from tempQueue and send to remoteQueue ... ...当接收器可用时,将消息从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(); 

I like this approach because it's fully transactional; 我喜欢这种方法,因为它完全是交易性的; if anything goes wrong, you don't lose messages provided you use PERSISTENT mode. 如果出现任何问题,只要您使用PERSISTENT模式,就不会丢失消息。 Also, when pulling message from tempQueue , you must use a synchronous receiver (as above), you can't use onMessage() since it processes messages from the local queue immediately. 此外,从tempQueue提取消息时,必须使用同步接收器(如上所述),因为它会立即处理来自本地队列的消息,所以不能使用onMessage()

Option 2 (Simpler, Less Safe) 选项2(更简单,更安全)

You can also use in-memory queue (not JMS ) for storing the message content locally: 您还可以使用内存中队列(而不是JMS)在本地存储消息内容:

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

Your application checks for resource availability on the receiving side, if it's available, just dequeue and send the real JMS messages with no delay: 您的应用程序检查接收端的资源可用性,如果可用,只需出列并立即发送真实的JMS消息:

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

The problem with this approach is that messages stored in queue reside in memory; 这种方法的问题是存储在queue中的消息驻留在内存中; if the sender crashes, you'll lose those message. 如果发件人崩溃,你将丢失这些消息。

Hope it helps! 希望能帮助到你!

Normally to delay receiving of the messages until the resources are ready, the connection.start() method is not invoked. 通常,为了延迟接收消息,直到资源准备就绪,不会调用connection.start()方法。 Here is the logic: 这是逻辑:

  1. The receiver starts and makes a connection and sets up all JMS resources. 接收器启动并建立连接并设置所有JMS资源。
  2. The connection.start() is not invoked. 不调用connection.start()。
  3. Wait for other resources to initialize 等待其他资源初始化
  4. Start the JMs connection using connection.start() 使用connection.start()启动JM连接

You can even pause the messages to be received by the message listener using this method. 您甚至可以使用此方法暂停消息侦听器接收的消息。 This technique is very common in GUI tools that use JMS. 这种技术在使用JMS的GUI工具中非常常见。

Assuming your using Websphere MQ, I don't thinks it's supported. 假设您使用的是Websphere MQ,我认为它不受支持。

JMS 2.0 does have support for delayed delivery[1] of messages, but without more information it's tough to answer. JMS 2.0确实支持延迟传递[1]消息,但没有更多信息,很难回答。

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

You can have your receiver block if the external resource is not ready. 如果外部资源未准备好,您可以让接收器阻塞。 Since the receiver is "busy" no more messages will be pulled off of the queue while it is blocked. 由于接收器“忙”,在阻塞时不会再从队列中取出消息。

Have you looked at the time-to-deliver setting for JMS objects configured in the WebLogic server? 您是否查看了WebLogic服务器中配置的JMS对象的交付时间设置?

Oracle WebLogic docs Oracle WebLogic文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM