【问题标题】:Spring AMQP Message delaySpring AMQP 消息延迟
【发布时间】:2016-09-21 09:14:54
【问题描述】:

我的问题和这个很相似:Why is there a delay in Spring AMQP Message dispatching from a filled Queue?

即使队列已填满消息,我也可以看到消息侦听器的两次调用之间存在延迟。我已经在日志消息中添加了方法开始时的时间、结束时间以及使用该方法的时间(以毫秒为单位):

开始 - 结束 - 时间
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;

处理消息的时间约为 10 毫秒(平均),但我可以看到延迟大于 50 毫秒(有时大于 100 毫秒)。

如果我将 SimpleMessageListenerContainer 的参数 PrefetchCount 改成 200(例如改为 200),那么性能会大大提高,现在我可以在日志中看到延迟消失了:

开始 - 结束 - 时间
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;

我的问题是:

  • 是什么导致了这种延迟?真的是网络延迟吗?我如何证明这一点?
  • 我在有关“prefetchCount”的文档中看到:“这越高,消息传递的速度越快,但非顺序处理的风险就越高。”那真的是什么意思?如果我需要按顺序处理消息,我可以让“prefetchCount”的值大于 1 吗?

我的配置是这样的:

    @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();
}

【问题讨论】:

    标签: spring-amqp


    【解决方案1】:

    是的;是网络。您可以使用网络监视器“证明”它。默认情况下,prefetchCount 是 1,这意味着代理只允许消费者收到一条未确认的消息。只有当该消息被确认时,才会发送下一个消息。

    增加预取计数会显着提高性能,但可能会导致无序交付。

    这到底是什么意思?

    假设预取计数为 10。您处理了 5 条消息,然后出现故障 (#6),消息被拒绝并重新排队(如果这样配置)。

    当您消耗完所有预取的消息后,消息 #6 将被重新传递 - 因此它会出现故障。

    如果您从不重新排队消息,则消息传递顺序没有问题。

    【讨论】:

    • 谢谢加里。那么 AcknowledgeMode.NONE 呢?应该比拥有一个非常大的 prefetchCount 更好吗?
    • 我不知道您所说的“非常大”是什么意思,但是,是的,它应该相当大。我们在使用NONE 时没有设置basicQos,因此代理会尽快发送消息。对于 1.3.0 之前的版本,如果侦听器跟不上,这可能会导致内存不足的情况。在 1.3.0 及更高版本中,我们使用 prefetchCount 来保持该数量的消息准备就绪,并在侦听器跟不上时阻止传递。
    • 请理解,但如果服务器出现故障,您将丢失任何使用该模式预取的消息。您可以将 ackmode AUTO 与 txSize=100 一起使用,以仅每 100 条消息发送一个 ack。不过,在这种情况下,您可能会得到重复。
    猜你喜欢
    • 2010-11-11
    • 1970-01-01
    • 2014-09-27
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    相关资源
    最近更新 更多