[SpringBoot] RabbitMQ コンシューマー確認モードを統合

消費者側

ディレクトリ構造

依存関係のインポート

yml を変更する

ビジネスの論理

自動確認

手動確認


消費者側

ディレクトリ構造

 

依存関係のインポート

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
        <version>2.5.0</version>
    </dependency>
</dependencies>

yml を変更する

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener:
      simple:
        acknowledge-mode: auto

        直接リスナーと単純リスナーの 2 種類のリスナーがあることがわかります。前者は直接スイッチに使用され、後者は他のスイッチに使用されます。

         自動確認モードには、none、auto、manual の 3 つのモードがあることがわかります。

        確認モード: none は自動的にメッセージを確認することを意味します (デフォルト)

        確認モード: 手動メッセージを確認する手段

        確認モード: 自動は、例外に従ってメッセージを確認することを意味します

        自動確認とは、コンシューマーがメッセージを受信すると、受信を自動的に確認し、RabbitMQ のメッセージ キャッシュからメッセージを削除することを意味します。しかし、実際の業務では、メッセージが受信されて業務処理が異常になり、メッセージが失われる可能性が非常に高くなります。手動確認方式の場合、業務処理成功後にchannel.basicACK()を呼び出し、例外が発生した場合はchannel.basicNack()を呼び出してメッセージを自動再送させる必要があります。

ビジネスの論理

自動確認

/**
 * 消费者自动确认消息
 * 1、yml中需要配置acknowledge-mode: none
 * 2、消费者监听实现MessageListener 
 */
@Component
public class AckListener implements MessageListener {

    @RabbitListener(queues = "test_queue_name")
    @Override
    public void onMessage(Message message) {
        System.out.println("消费者接受的消息为:" + new String(message.getBody()));
    }
}

手動確認

/**
 * 消费者手动确认消息
 * 1、yml中需要配置acknowledge-mode: manual
 * 2、消费者监听实现ChannelAwareMessageListener 
 */
@Component
public class AckListener implements ChannelAwareMessageListener {

    @RabbitListener(queues = "test_queue_name")
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        // 消息的唯一标识id
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            System.out.println("消费者接受的消息为:" + new String(message.getBody()));
            // 手动签收的第一个参数为消息的唯一标识id、第二个参数表示是否批量签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e){
            // 手动拒绝签收的第一个参数为消息id、第二个参数表示是否批量签收
            // 第三个参数消息是否重回队列
            channel.basicNack(deliveryTag,true,true);
            System.out.println("消息被拒绝签收了");
        }
    }
}

/**
 * 消费者手动确认消息
 * 1、yml中需要配置acknowledge-mode: manual
 * 2、消费者监听实现ChannelAwareMessageListener 
 */
@Component
public class AckListener implements ChannelAwareMessageListener {

    @RabbitListener(queues = "test_queue_name")
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        // 消息的唯一标识id
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            System.out.println("消费者接受的消息为:" + new String(message.getBody()));
            int i = 1 / 0;//业务逻辑故意出错进入catch块
            // 手动签收的第一个参数为消息的唯一标识id、第二个参数表示是否批量签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e){
            // 手动拒绝签收的第一个参数为消息id、第二个参数表示是否批量签收
            // 第三个参数消息是否重回队列
            channel.basicNack(deliveryTag,true,true);
            System.out.println("消息被拒绝签收了");
        }
    }
}

        注: 上記の端末は、channel.basicNack() メソッドの 3 番目のパラメーターによってメッセージが再送信のためにキューに戻されるため、無限ループが発生しますが、try のビジネス ロジック ブロックには常に問題があるため、繰り返し報告されます。 3 番目のパラメータが false で、結果が次の場合はエラー。

おすすめ

転載: blog.csdn.net/m0_65563175/article/details/130455209