不终止的 JMS 客户端

问题描述 投票:0回答:1

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

}
java jms
1个回答
2
投票

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

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

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

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

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

要解决此问题,您的

main()
方法应在创建
JmsTestWithoutClose
实例后等待。在 Java 中有很多方法可以做到这一点:

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

在任何情况下,应用程序关闭其创建的所有资源(例如会话、连接等)都很重要。

© www.soinside.com 2019 - 2024. All rights reserved.