消費端channel主動斷開後,可能存在的bug

和我之前關聯的博客:https://blog.csdn.net/h996666/article/details/83378576

消費端代碼如下:

package com.mq;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeoutException;

public class ConsumerTest {

    public static void main(String[] args) {
        // 創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        // 連接
        Connection connection = null;
        // 通道
        Channel channel = null;

        try {
            // 設置URL
            factory.setUri("amqp://testuser:[email protected]:5672/my_test");
            // 獲取連接
            connection = factory.newConnection();
            // 創建通道
            channel = connection.createChannel();

            // 創建消費對象
            Consumer consumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag,
                                           Envelope envelope,
                                           AMQP.BasicProperties properties,
                                           byte[] body) throws IOException {
                    String msg = new String(body, "UTF-8");

                    //TODO 自己的業務
                    System.out.println("Received message : " + msg);

                    // 處理完業務之後,手動刪除消息
                    this.getChannel().basicAck(envelope.getDeliveryTag(), false);
                }
            };

            /**
             * 消費消息
             * queue 隊列名稱
             * autoAck true,消費端收到消息後,隊列自動刪除消息
             *         false,消費端收到消息後,需手動刪除消息
             * callback 消費者對象
             */
            channel.basicConsume("testQueue", false, consumer);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (channel != null) {
                    channel.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    }
}

在最後我加了finally代碼塊,顯示的關閉channel,connection。

在運行過程我發現了問題:業務端代碼沒有被執行。

@Override
public void handleDelivery(String consumerTag,
                           Envelope envelope,
                           AMQP.BasicProperties properties,
                           byte[] body) throws IOException {
    String msg = new String(body, "UTF-8");

    //TODO 自己的業務
    System.out.println("Received message : " + msg);

    // 處理完業務之後,手動刪除消息
    this.getChannel().basicAck(envelope.getDeliveryTag(), false);
}

上面代碼沒有被執行。

具體問題如下:

1,消息自動刪除的模式下:消息被刪除,但是業務未被執行。

2,消息需要回執的模式下:消息未被刪除,業務也未被執行。

個人猜想:

導致這個問題可能原因:消費端的業務代碼,是異步執行的。

這個得要看源碼才能證實。

 

另外我這裏只是測試,在真實應用中,是不可能每次使用時去創建關閉connection,channel,

況且我使用的rabbitmq的架包只是基礎架包,就像jdbc,jedis那樣的。

真實應用中,肯定也是採用連接池的機制,來減少不必要的性能消耗。

官方文檔中關於connection和channel的生命週期的描述:

http://www.rabbitmq.com/api-guide.html#connection-and-channel-lifspan

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章