【问题标题】:Close RabbitMQ channels and connections properly正确关闭 RabbitMQ 通道和连接
【发布时间】:2018-01-29 17:46:23
【问题描述】:

我目前正在运行一个基本的 RabbitMQ 主题发布,每 3 秒发布一次。

我的班级是这样的:

import com.rabbitmq.client.*;

import java.io.IOException;

public class EmitLogTopic {

    private static final String EXCHANGE_NAME = "topic_logs";

    @Scheduled(fixedRate = 3000)
    public void publish(String[] argv)
                  throws Exception {

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "topic");

        String routingKey = getRouting(argv);
        String message = getMessage(argv);

        channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
        System.out.println(" [x] Sent '" + routingKey + "':'" + message + "'");

        channel.close();
        connection.close();
    }
    //...
}

我希望每次运行方法发布时,它都会发布,然后通道和连接都关闭,防止每 3 秒有一个新的通道和连接卡在内存中。

但是,当我查看我的 RabbitMQ 管理界面(在概览页面)时,全局计数部分显示连接总数和通道总数都在不断增加。

最终,由于达到了 Socket 限制和内存限制,我的应用程序崩溃了。

所以看起来 close() 并没有删除使用的通道和连接,并且仍然将它们保留在内存中,最终导致所有内存被消耗。在通道和连接上使用什么正确方法来确保他们不会这样做?

【问题讨论】:

  • 你不能重复使用相同的连接和通道,而不是每次都创建它们吗?
  • 您应该保持一个通道打开并将其用于多条消息。
  • @Berger 嗨,我最初是使用 AMQP 执行此操作的,它在应用程序首次启动时创建连接和通道。但是,我的新要求是我必须能够即时更改主机、用户名和密码,而不必停止应用程序。
  • @OrangeDog 由于这个限制,我明确地创建了连接,因此在创建时我可以设置连接的本地主机、用户名和密码,而无需停止应用程序。
  • 您应该只覆盖相关的工厂和/或配置,而不是完全重新实现spring-amqp

标签: java spring rabbitmq connection channel


【解决方案1】:

但是,当我查看我的 RabbitMQ 管理界面时(在概览 页),全局计数部分显示,两者的总数 连接和渠道不断增加。

我认为你的连接有问题。

检查您操作系统中的 TCP 连接,例如:

1. netstat -anp | grep :5672 | grep ESTABLISHED | wc -l

还可以使用命令行工具检查您的连接:

2. rabbitmqctl list_connections 如果您在12 中有很多连接,则意味着您没有以正确的方式关闭连接/通道。

如果您需要处理大量连接,您可以增加文件描述符配置:

例如https://www.rabbitmq.com/install-debian.html

使用 systemd(最近的 Linux 发行版)

在使用 systemd 的发行版上,操作系统限制通过 配置文件在 /etc/systemd/system/rabbitmq-server.service.d/limits.conf,用于 示例:

[服务] LimitNOFILE=300000

编辑

您发布的代码很好,close() 方法是关闭连接的正确方法。

如果您执行代码,您应该在您的真实代码中进行调查。

如果有,还要检查日志内部:

=INFO REPORT==== 22-Aug-2017::09:23:28 ===
connection <0.383.0> ([::1]:60590 -> [::1]:5672): user 'guest' authenticated and granted access to vhost '/'

=INFO REPORT==== 22-Aug-2017::09:23:37 ===
closing AMQP connection <0.383.0> ([::1]:60590 -> [::1]:5672, vhost: '/', user: 'guest')

closing AMQP connection 是关闭连接

【讨论】:

  • 感谢您的回复。根据通过命令行的检查,我确实有很多连接,这意味着我没有正确关闭我的连接。但我认为通过使用方法 close(),我应该期望连接关闭,不是吗?我也尝试过使用方法 abort(),但也没有运气。您是否知道我应该使用什么代码来关闭悬空连接?谢谢。
  • 即使我也面临同样的问题。连接根本没有关闭
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
相关资源
最近更新 更多