【问题标题】:How can I cleanly shut down a RabbitTemplate in Spring Rabbit?如何在 Spring Rabbit 中干净地关闭 RabbitTemplate?
【发布时间】:2016-08-19 19:52:47
【问题描述】:

我编写了一个脚本,它使用 Spring Rabbit 将一些消息放在使用 RabbitTemplate.convertAndSend 的 Rabbit 队列中,然后退出。但是,即使在消息已入队后,Rabbit 连接似乎仍使应用程序保持活动状态。我还没有找到一种方法来干净地告诉 Rabbit 服务器在消息入队后停止。

我能想到的最佳解决方案是将我的 convertAndSend 调用更改为 convertSendAndReceive,以便我知道消息已成功入队,然后使用 System.exit(0) 退出。我切换到 convertSendAndReceive,因为它似乎 convertAndSend 发生在后台线程或类似的线程中,因为如果我在执行多次这些调用后执行 System.exit(0),那么只有前这么多会成功。

请注意,仅创建 RabbitTemplate 不会导致此行为;通过“发送”方法之一使用它。

以下代码说明了这个问题。

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import static issues.RabbitSettings.*; //Static fields containing my test Rabbit connection info

public class RabbitTemplateShutdownIssue {
    public static void main(String[] args) {
        RabbitTemplate rabbitTemplate = createRabbitTemplate();
        rabbitTemplate.convertAndSend(ROUTING_KEY, "Test"); // Or convertSendAndReceive
        // The app never exits
    }

    private static RabbitTemplate createRabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
        rabbitTemplate.setExchange(EXCHANGE);
        rabbitTemplate.setMandatory(true);
        return rabbitTemplate;
    }

    private static ConnectionFactory getConnectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(HOSTNAME);
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setVirtualHost(VIRTUAL_HOST);
        connectionFactory.setUsername(USERNAME);
        connectionFactory.setPassword(PASSWORD);
        return connectionFactory;
    }
}

有没有办法告诉 Rabbit 客户端关闭,最好是在所有消息都入队之后?

【问题讨论】:

  • 关闭 Spring。您正在使用带有ApplicationContext 的 Spring Beans - 这是一个要处理的 PITA,因为您需要按顺序关闭事物,以免出现异常。简单的解决方案?做正确的事!
  • @BoristheSpider 在我的示例中没有运行 Spring 容器,因此没有要关闭的 Spring。
  • 这正是我的观点。 (我现在明白了,我的意思是“没有”而不是“有”)
  • @BoristheSpider 看起来你在我开始写回复后编辑了你的评论,因为我看到并正在回复的评论只是“关闭春天”。有了这个额外的上下文,你的回答就更有意义了。

标签: java spring rabbitmq spring-rabbit


【解决方案1】:

如果让 Spring 管理 bean,则完成后可以close() 应用程序上下文。

您现在配置它的方式(没有 Spring 上下文),您可以在连接工厂上调用 destroy(),一切都会关闭。

对这样的事情使用静态方法是一种反模式;您需要将工厂存储在静态字段中,以便您可以销毁模板正在使用的工厂。

你需要一个确认回调来确认兔子收到了发送。

【讨论】:

  • 公平地说,实际的脚本是一个 Groovy 脚本,它执行一些基本的消息排队然后退出,而不是一个成熟的生产应用程序。我只是用静态方法编写了我的示例,因为使用 Java 似乎比 Groovy 更能保证被 Spring 观众理解。
  • 很公平。您需要在模板上进行确认回调,以确认兔子收到了发送。
  • 连接工厂的destroy()正是我要找的。​​span>
猜你喜欢
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多