If there are two active consumers, the broker will distribute new messages fairly (until each instance has 200 outstanding).
If there are 150 messages in the queue and no consumers running; the first consumer to start will (likely) get all 150, but when both are running, the distribution is fair.
If there are 200 outstanding at each consumer, the broker will send new messages on demand as each one is ack'd. The consumer thread is not "blocked", it is just that the broker will send no more messages.
By default, spring will ack each message one-at-a-time. This behavior can be changed by setting the container's batchSize
property. e.g. if it is set to 100, it will send an ack every 100 records; this improves performance, but adds the risk of duplicate deliveries after a failure. In this case, the broker will send up to 100 new messages after the ack.
In older versions, batchSize
was called txSize
.
EDIT
See this for an example; the default prefetch is 250 in recent versions.
@SpringBootApplication
public class So65201334Application {
public static void main(String[] args) {
SpringApplication.run(So65201334Application.class, args);
}
@RabbitListener(id = "foo", queues = "foo", autoStartup = "false")
@RabbitListener(id = "bar", queues = "foo", autoStartup = "false")
void listen(String in, @Header(AmqpHeaders.CONSUMER_TAG) String tag) throws InterruptedException {
System.out.println(tag);
Thread.sleep(240_000);
}
@Bean
public ApplicationRunner runner(RabbitTemplate template, RabbitListenerEndpointRegistry registry) {
return args -> {
for (int i = 0; i < 200; i++) {
template.convertAndSend("foo", "bar");
}
registry.getListenerContainer("foo").start();
System.out.println("Hit Enter to start the second listener and send more records");
System.in.read();
registry.getListenerContainer("bar").start();
Thread.sleep(2000);
for (int i = 0; i < 200; i++) {
template.convertAndSend("foo", "bar");
}
};
}
}
As expected, all 200 went to the first consumer:
When the second consumer is started, the records are sent to both consumers, not the one that has no backlog. With the distribution now looking like this:
When I increase the prefetch to 400, you can see that the new messages go 50% to each consumer.