jandres
jandres

Reputation: 479

Spring AMQP Message delay

My question is very similar to this one: Why is there a delay in Spring AMQP Message dispatching from a filled Queue?

I can see a delay between two invocations of my message listener even when the queue is filled with messages. I have put a log message with the time at the very begining of the method, the time at the end, and the time that took the method (in milliseconds):

Start - End - Time
2016-09-21T10:08:55.263; - 2016-09-21T10:08:55.278; - 15;
2016-09-21T10:08:55.356; - 2016-09-21T10:08:55.356; - 0;
2016-09-21T10:08:55.388; - 2016-09-21T10:08:55.388; - 0;
2016-09-21T10:08:55.466; - 2016-09-21T10:08:55.466; - 0;

The time processing the message is about 10 ms (in average) but I can see delays greater tan 50 ms (sometimes greater tan 100 ms).

If I change the parameter PrefetchCount of the SimpleMessageListenerContainer (for example to 200), then the performance increase considerabily, and now I can see in the logs that the delay has desapear:

Start - End - Time
2016-09-21T10:26:27.336; - 2016-09-21T10:26:27.336; - 0;
2016-09-21T10:26:27.336; - 2016-09-21T10:26:27.351; - 15;
2016-09-21T10:26:27.351; - 2016-09-21T10:26:27.351; - 0;
2016-09-21T10:26:27.351; - 2016-09-21T10:26:27.351; - 0;

My questions are:

My configuration is like this:

    @Bean   
    public MessageListenerAdapter broadcastMessageListenerAdapter() {
       return new MessageListenerAdapter(myHandlerBroadcast(), "onMessage");
    }

@Bean(name="myBroadcastMessageListenerContainer") 
public SimpleMessageListenerContainer myBroadcastMessageListenerContainer() 
{
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(myConnectionFactory());
    container.setQueueNames(PX_BROADCAST_QUEUE + environment.getProperty("my.user"));
    container.setMessageListener(broadcastMessageListenerAdapter());
    container.setAcknowledgeMode(AcknowledgeMode.AUTO);
    container.setMessageConverter(myMessageConverter());
    container.setConcurrentConsumers(1);
    container.setAutoStartup(false);
    container.setPrefetchCount(500);        // ¿1?
    return container;
 }

@Bean(name="myHandlerBroadcast")
public MyHandlerBroadcast myHandlerBroadcast(){
  return new MyHandlerBroadcast();
}

Upvotes: 1

Views: 177

Answers (1)

Gary Russell
Gary Russell

Reputation: 174554

Yes; it's network. You can "prove" it by using a network monitor. By default prefetchCount is 1 which means the broker only allows one un-acked message at the consumer. Only when that message is ack'd is the next one sent.

Increasing the prefetch count dramatically increases performance but can cause out-of-order delivery.

What that really mean?

Consider a prefetch count of 10. You process 5 messages and then have a failure (#6) and the message is rejected and requeued (if so configured).

Message #6 will be redelivered when you have consumed all your prefetched messages - hence it will be out of order.

If you never requeue messages then there is no problem with message delivery order.

Upvotes: 3

Related Questions