コンシューマの現在の制限は、コンシューマがメッセージを受け取るたびにメッセージの数を制限するために使用されます。前提は手動確認モードであることに注意してください。また、メッセージは手動で確認した後にのみ取得できます。
消費者側
ディレクトリ構造
依存関係のインポート
<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: manual # 手动确认模式
prefetch: 1 # 每次消费仅1条消息
ビジネスの論理
実際にメッセージをコンシュームするために手動での確認が必要かどうかを検証するために、次のようなテストを行いました。まず、下の図 1 に示すように、キューに 2 つのメッセージを生成するようプロデューサーに依頼しました。次に、コード ロジックを見てください。コンシューマーコードを起動すると、下の図 2 のようになります。確かに電流は制限されており、未確認のメッセージが表示されますが、コンシューマー側でアプリケーションを閉じると、再び図 1 のようになります。
図1
/**
* 消费者的限流机制
* 1、确保Ack机制为手动机制:acknowledge-mode: manual
* 2、每次消费消息的个数:prefetch: 1 只有手动确认完后才会拉取下一条消息
*/
@Component
public class QosListener implements ChannelAwareMessageListener {
@RabbitListener(queues = "test_queue_name")
@Override
public void onMessage(Message message, Channel channel) throws Exception {
System.out.println("消费者接受的消息为:" + new String(message.getBody()));
}
}
図2
そのため、ビジネス ロジックを再度変更すると、手動で確認した後、図 3 に示すように、メッセージが実際に消費されていることがわかります。注意: バッチにサインインするかどうかの 2 番目のパラメーターは、コンシューマーがオンになった後にメッセージが一度だけ読み取られるかどうかを示し、コンシューマーの電流制限プリフェッチは、各読み取りが 1 つのメッセージしか読み取ることができないことを示します。両者のコンセプトは異なります。
/**
* 消费者的限流机制
* 1、确保Ack机制为手动机制:acknowledge-mode: manual
* 2、每次消费消息的个数:prefetch: 1 只有手动确认完后才会拉取下一条消息
*/
@Component
public class QosListener implements ChannelAwareMessageListener {
@RabbitListener(queues = "test_queue_name")
@Override
public void onMessage(Message message, Channel channel) throws Exception {
Thread.sleep(5000);
long deliveryTag = message.getMessageProperties().getDeliveryTag();// 消息的唯一标识id
System.out.println("消费者接受的消息为:" + new String(message.getBody()));
channel.basicAck(deliveryTag,true);//每5s读一次消息(限流后每次为一条)
}
}