Springbootはrabbitmq手動AKCメカニズムを統合します

シナリオ:rabbitmqサーバーがダウンしている場合、メッセージは処理されています。この時点では、メッセージは処理されませんが、エラーは報告されません。MQを再起動すると、メッセージが消えます。
解決策:手動ACK
手動ACK:ただし、が完了すると、キューが完了したことを手動でキューに通知します。キューに通知しない場合、メッセージは常にキューに保存されます。

channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);	
告诉队列已经消费完成。参数1 当前消息的索引位置,
第二个参数是否批量ACK该索引之前的消息
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
告诉队列消费失败
参数1 当前消息的索引位置 
第二个参数是否批量ACK该索引之前的消息 
第三个参数 是否重回队列 

構成ファイル

server:
  port: 8093
spring:
  rabbitmq:
    host: 192.168.1.36
    port: 5672
    username: cll
    password: cll@2020
    listener:
      simple:
        retry:
          enabled: true
          multiplier: 2 #乘子 默认是1
          max-attempts: 5 #最大重试次数 默认是3
          max-interval: 20000000  #最大重试间隔 默认是10000毫秒 也就是10s
          initial-interval: 3000 # 间隔多少重试
        default-requeue-rejected: false #false 消息被拒绝以后不会重新进入队列,超过最大重试次数会进入死信队列
        acknowledge-mode: manual #默认auto
        #NONE 可以称之为自动回调,即使无响应或者发生异常均会通知队列消费成功,会丢失数据。
        #AUTO 自动检测异常或者超时事件,如果发生则返回noack,消息自动回到队尾,但是这种方式可能出现消息体本身有问题,返回队尾其他队列也不能消费,造成队列阻塞。
        #MANUAL 手动回调,在程序中我们可以对消息异常记性捕获,如果出现消息体格式错误问题,手动回复ack,接着再次调用发送接口把消息推到队尾。

次に、コンシューマーコードを変更します

@Component
public class DelListener {

    @RabbitListener(queues = "cme_UploadZJFace")
    public void listener(Message message, Channel channel) throws IOException {
        SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd hh mm ss");
        String s = sd.format(new Date()).toString();
        System.out.println("消费中---------------------------"+s);
        try {
            int i=1/0;
            //channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            System.out.println("消费失败---------------------------"+s);
            //channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
            e.printStackTrace();
        }
    }
    @RabbitListener(queues = "REDIRECT_QUEUE")
    public void receiveA(Message message){
        System.out.println("进入死信队列");
    }


}

メッセージを送信
ここに画像の説明を挿入
して、MQ管理ページ
ここに画像の説明を挿入
を見つけて確認します。キューには常にメッセージがあります。
次に、ACKコメントとNACKコメントを削除します。プロジェクトを再開します。
ここに画像の説明を挿入
ここに画像の説明を挿入このメッセージは、NACKの後にデッドレターキューに直接入ることがわかります。
再試行はありません。
管理ページをもう一度見てください。
ここに画像の説明を挿入
次に他のcath例外情報を試し
、IO例外に置き換えています。

@RabbitListener(queues = "cme_UploadZJFace")
public void listener(Message message, Channel channel) throws IOException {
    SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd hh mm ss");
    String s = sd.format(new Date()).toString();
    System.out.println("消费中---------------------------"+s);
    try {
        int i=1/0;
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    } catch (IOException e) {
        System.out.println("消费失败---------------------------"+s);
        channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
        e.printStackTrace();
    }
}

ここに画像の説明を挿入
コンソール情報は、5回再試行しなかったが、デッドレターキューに入らなかったことを検出しました。
手動確認応答を設定すると、手動ACKでのみメッセージを確認応答し、手動NACKはデッドレターキューに入ります。

おすすめ

転載: blog.csdn.net/ChenLong_0317/article/details/105416126