RabbitMQ单机消费者设置合理的并发数与prefetch Count策略

写在前面

最开始我们使用rabbitmq的时候可能只会用一个消费和一个prefetch Count,如下图所示。

image.png

随着生产者发送消息量变大,等到生产者发送速度大于消费者消费速度就会产生消息挤压。这个时候我就要考虑设置设置并发数和prefetch Count

设置prefetch Count

https://www.rabbitmq.com/blog/2014/04/14/finding-bottlenecks-with-rabbitmq-3-3/这篇博客告诉我们设置多少合理。经过作者的测试,preprefetch Count设置30是合理的,如果preprefetch Count值再变大,消费速度基本没变。这篇博客也告诉了我们一个观察消费速率的指标Consumer utilisation,对应的这个值越大,消费投放速度越快,消息处于空闲的时间会越短。

并发数

试想以下场景,消费者设置一个并发,一个prefetch count,这个时候rabbitmq中有AB两条消息,其中A消息推送给了消费者,B消息还在rabbitmq队列中,消费者处理A消息需要1s。这个时候消费者在处理A消息,但是B消息还在队列中休息,静静的等着推送给消费者,B消息休息的时间就是消息的空闲时间。

image.png

下图中显示了B消息的空闲期。
image.png

增大并发数也可以减少B消息的空闲时间,那么并发数设置多少合适??并发数设置大了就会加大线程对资源抢夺,增加上下文切换频率等反而有可能会降低消费速度,并发数少了CPU的利用率低。这里提供一个公式:并发数=核数 * (x+y)/x,其中x是线程执行时间,y是阻塞等待时间。
关于阻塞:

  1. 这里的阻塞指的是会释放CPU的阻塞,比如网络编程的accept()等待客户端连接,recv()等待下游回包。
  2. while(true) { i ++;} 这种阻塞就不会释放CPU

关于公式推导:
如下图,假设是单核CPU,并且线程工作时间需要2ms,阻塞时间为2ms,那么只要设置两个线程就可以让CPU跑到100%。

image.png

可以看到,只要在前一个线程一旦处于空闲时间中,后面的任务能够立马被执行,线程就可以跑到100%,如果单核CPU,线程工作2ms,阻塞时间为3ms,那么我们就需要3个线程保证cpu跑到100%,所以线程数就是(执行时间+空闲时间)/执行时间,如果有小数,那么就向上取整。所以如果是NCPU,最佳的设置的线程数是=N*((执行时间+空闲时间)/执行时间)
image.png

所以在单机上,rabbitmq消费者设置的合理并发数是:N*((消费消费时间+消息在网络传递时间)/消费消费时间)
image.png

你可能感兴趣的:(RabbitMQ单机消费者设置合理的并发数与prefetch Count策略)