gpt4 book ai didi

java - 不终止的 JMS 客户端

转载 作者:行者123 更新时间:2023-12-02 10:32:50 28 4
gpt4 key购买 nike

我们有一个 JMS 客户端,需要保持空闲状态直到收到消息。当它收到消息时,它将执行一些功能,然后返回到空闲状态。我的问题是,确保客户端保持正常运行的最佳方法是什么?让 JMS 客户端软件处理这个问题是个好习惯还是我们需要在主机上将软件作为服务运行(和/或执行其他操作)?我们目前依赖 JMS 客户端软件,因为它似乎通过打开的连接保持线程 Activity ,但我不确定这是否是最佳实践。我们使用 ActiveMQ 作为消息代理和客户端软件。

编辑:添加代码示例

下面是客户端如何使用 JMS 客户端连接保持正常运行的示例:

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;

public class JmsTestWithoutClose implements MessageListener {

private final Connection connection;
private final Session session;
private final MessageConsumer consumer;

public static void main(String[] args) throws JMSException {
System.out.println("Starting...");
JmsTestWithoutClose test = new JmsTestWithoutClose("<username>", "<password>", "tcp://<host>:<port>");
// if you uncomment the line below, the program will terminate
// if you keep it commented, the program will NOT terminate
// test.close();
System.out.println("Last line of main method...");
}

public JmsTestWithoutClose(String username, String password, String url) throws JMSException {
// create connection and session
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(username, password, url);
this.connection = factory.createConnection();
connection.start();
this.session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createTopic("Topic_Name");
consumer = session.createConsumer(destination);
consumer.setMessageListener(this);
}

public void close() throws JMSException {
session.close();
connection.close();
}

@Override
public void onMessage(Message message) {
// process the message
}

}

最佳答案

当前的客户端实现是否满足您的要求?如果是这样,我不会改变它。如果当前的客户端实现不能满足您的要求,那么我会更改它。仅仅为了坚持“最佳实践”而更改运行正常并满足您的需求(并且没有明显可预见的问题)的软件几乎肯定不是最好的资源投资。

最终应用程序的行为取决于应用程序本身。我不明白将应用程序作为服务运行或在应用程序外部执行任何其他操作实际上会强制它在监听/等待消息时保持正常运行并正常运行。如果应用程序被编程为使用 JMS API 并创建 MessageListener(即负责异步接收消息的类),然后在没有实际等待消息的情况下退出,这将是一个错误。将此类应用程序作为服务运行,以便操作系统在错误退出后不断重新启动它,这并不是一个好的解决方案。

拥有一个正确编写的客户端是最佳实践。用一些外部机制来支撑它是不好的做法。

您提供的示例代码写得不好,并且存在一些明显的问题:

  1. ConnectionSession 对象超出范围,这意味着它们永远无法正确关闭。最终这些对象将被 JVM 进行垃圾回收。这是不正确的资源管理。
  2. 应用程序未完全终止的唯一原因是 ActiveMQ 5.x 客户端的实现方式(即打开的连接阻止 JVM 进程终止)。此实现细节不是 JMS API 提供的公共(public)契约的一部分,因此不应依赖。如果您要使用不同的 JMS 客户端实现,例如对于 ActiveMQ Artemis 核心 JMS 客户端,一旦 main() 退出,应用程序就会完全终止。

要解决此问题,您的 main() 方法应在创建 JmsTestWithoutClose 实例后等待。在 Java 中,有很多方法可以做到这一点:

  1. while 循环与 Thread.sleep() 结合使用,其中可以根据需要修改循环条件以允许应用程序退出。
  2. 使用专门为线程协调设计的对象,例如 java.util.concurrent.CountDownLatch 。使用 CountDownLatchmain() 方法可以调用 await(),当应用程序完成消息处理时,MessageListener > 例如,实现可以调用 countDown()
  3. 使用 while 循环从控制台读取输入,并且仅在输入特殊字符串时继续(例如 exit)。

无论如何,应用程序关闭其创建的所有资源(例如 session 、连接等)非常重要。

关于java - 不终止的 JMS 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53511049/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com