RabbitMQ 教程

关闭连接,释放资源

前面章节分别介绍了怎样创建连接、声明交换器、声明队列、发送消息和消费消息。本章节将介绍 RabbitMQ 程序开发的最后一步,那就是关闭连接,释放资源。它包含释放信道(Channel)、连接(Connection),代码如下:

channel.close();
connection.close();

显示地关闭信道 Channel 是一个好习惯,但并不是必须的。在连接 Connection 关闭的时候,信道 Channel 会自动关闭。关闭资源的模板代码:

Connection connection = null;
Channel channel = null;
try {
    // 创建连接
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("127.0.0.1");
    factory.setPort(5672);
    connection = factory.newConnection();
    
    // 创建通道
    channel = connection.createChannel();
    
    //...业务代码
} finally {
    if(null != channel){
        channel.close();
    }
    if(null != connection) {
        connection.close();
    }
}

AMQP 中 Connection 和 Channel 采用同样的方式来管理网络失败、内部错误和显示地关闭连接。Connection 和 Channel 具备如下声明周期:

  • Open:开启状态,代表当前对象可以使用。

  • Closing:正在关闭状态,当前对象被显示地通知调用关闭方法(shutdown),这样就产生了一个关闭请求让其内部对象进行相应的操作,并等待这些关闭操作的完成。

  • Closed:已经关闭状态,当前对象已经接收到所有的内部对象已完成关闭动作的通知,并且其也关闭了自身。

注意:不论程序正常调用关闭方法、还是客户端异常,甚至发生了网络异常。最终,Connection 和 Channel 都会成为 Closed 状态。

在 Connection 和 Channel 中,与关闭相关的方法如下:

  • addShutdownListener(ShutdownListener listener):添加关闭监听器。

  • removeShutdownListener(ShutdownListener listener):移除关闭监听器。

当 Connection 或者 Channel 的状态转变为 Closed 的时候会调用通过 addShutdownListener() 方法添加的 ShutdownListener 监听器。如果将一个 ShutdownListener 注册到一个已经处于 Closed 状态的 Connection 或者 Channel 对象时,会立刻调用 ShutdownListener 监听器。

下面是一些关闭辅助方法:

  • getCloseReason():方法可以让你知道对象关闭的原因。

  • isOpen():检测对象当前是否处于开启状态。

  • close(int closeCode, String closeMessage):方法显示地通知当前对象执行关闭操作。

ShutdownListener 监听器的使用方法示例代码如下:

// 创建连接
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
Connection connection = factory.newConnection();
// 添加监听器
connection.addShutdownListener(new ShutdownListener() {
   public void shutdownCompleted(ShutdownSignalException cause) {
      System.out.println("Connection Closed");
   }
});

// 创建通道
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
// 添加监听器
channel.addShutdownListener(new ShutdownListener() {
   public void shutdownCompleted(ShutdownSignalException cause) {
      System.out.println("Channel Closed");
   }
});

// 发送消息
System.out.println("[Send] Sending Message...");
byte[] msg = ("hello wrold " + System.currentTimeMillis()).getBytes();
channel.basicPublish(EXCHANGE_NAME, "www.hxstrive.com", null, msg);
System.out.println("[Send] msg = " + new String(msg));

运行上面代码,输出如下:

[Receive] Waiting Message...
[Send] Sending Message...
[Send] msg = hello wrold 1645455555718
[Receive] Receive Message :: hello wrold 1645455555718
Channel Closed
Connection Closed

当触发 ShuwdownListener 时,可以获取到 ShutdownSignalException,ShutdownSignalException 中包含了关闭的原因,这些可以通过调用 getCloseReason() 方法获取。代码如下:

channel.getCloseReason();
connection.getCloseReason();

调用上面代码,输出信息如下:

Channel Closed cause: com.rabbitmq.client.ShutdownSignalException: clean connection shutdown; protocol method: #method<connection.close>(reply-code=200, reply-text=OK, class-id=0, method-id=0)
[Receive] Receive Message :: hello wrold 1645455964149
Connection Closed cause: com.rabbitmq.client.ShutdownSignalException: clean connection shutdown; protocol method: #method<connection.close>(reply-code=200, reply-text=OK, class-id=0, method-id=0)

ShutdownSignalException 提供了多个方法来分析关闭的原因,方法如下:

  • isHardError():可以知道是 Connection 还是 Channel 的错误。如果返回 true,则表示 Connection 错误。如果返回 false,则表示 Channel 错误。

  • getReason():可以获取 cause 相关的信息。

上面方法的使用示例,代码如下:

// 创建连接
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
connection = factory.newConnection();

final Connection finalConn = connection;
connection.addShutdownListener(new ShutdownListener() {
    public void shutdownCompleted(ShutdownSignalException cause) {
        System.out.println("Connection Closed cause: " + finalConn.getCloseReason());
        if(cause.isHardError()) {
            System.out.println("Connection error,cause = " + cause.getReason());
        } else {
            System.out.println("Channel error,cause = " + cause.getReason());
        }
    }
});
说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号