寫(xiě)在前面
最開(kāi)始我們使用rabbitmq
的時(shí)候可能只會(huì)用一個(gè)消費(fèi)和一個(gè)prefetch Count
督赤,如下圖所示。
隨著生產(chǎn)者發(fā)送消息量變大拴清,等到生產(chǎn)者發(fā)送速度大于消費(fèi)者消費(fèi)速度就會(huì)產(chǎn)生消息擠壓靶病。這個(gè)時(shí)候我就要考慮設(shè)置設(shè)置并發(fā)數(shù)和
prefetch Count
。
設(shè)置prefetch Count
https://www.rabbitmq.com/blog/2014/04/14/finding-bottlenecks-with-rabbitmq-3-3/這篇博客告訴我們?cè)O(shè)置多少合理口予。經(jīng)過(guò)作者的測(cè)試娄周,preprefetch Count
設(shè)置30是合理的,如果preprefetch Count
值再變大沪停,消費(fèi)速度基本沒(méi)變煤辨。這篇博客也告訴了我們一個(gè)觀察消費(fèi)速率的指標(biāo)Consumer utilisation
,對(duì)應(yīng)的這個(gè)值越大牙甫,消費(fèi)投放速度越快掷酗,消息處于空閑的時(shí)間會(huì)越短。
并發(fā)數(shù)
試想以下場(chǎng)景窟哺,消費(fèi)者設(shè)置一個(gè)并發(fā),一個(gè)prefetch count
技肩,這個(gè)時(shí)候rabbitmq
中有A
且轨,B
兩條消息,其中A
消息推送給了消費(fèi)者虚婿,B
消息還在rabbitmq
隊(duì)列中旋奢,消費(fèi)者處理A
消息需要1s。這個(gè)時(shí)候消費(fèi)者在處理A
消息然痊,但是B
消息還在隊(duì)列中休息至朗,靜靜的等著推送給消費(fèi)者,B
消息休息的時(shí)間就是消息的空閑時(shí)間剧浸。
下圖中顯示了
B
消息的空閑期锹引。增大并發(fā)數(shù)也可以減少
B
消息的空閑時(shí)間,那么并發(fā)數(shù)設(shè)置多少合適唆香?嫌变?并發(fā)數(shù)設(shè)置大了就會(huì)加大線程對(duì)資源搶奪,增加上下文切換頻率等反而有可能會(huì)降低消費(fèi)速度躬它,并發(fā)數(shù)少了CPU
的利用率低腾啥。這里提供一個(gè)公式:并發(fā)數(shù)=核數(shù) * (x+y)/x
,其中x
是線程執(zhí)行時(shí)間,y
是阻塞等待時(shí)間倘待。關(guān)于阻塞:
- 這里的阻塞指的是會(huì)釋放CPU的阻塞疮跑,比如網(wǎng)絡(luò)編程的accept()等待客戶端連接,recv()等待下游回包凸舵。
-
while(true) { i ++;}
這種阻塞就不會(huì)釋放CPU
祸挪。
關(guān)于公式推導(dǎo):
如下圖,假設(shè)是單核CPU
贞间,并且線程工作時(shí)間需要2ms贿条,阻塞時(shí)間為2ms,那么只要設(shè)置兩個(gè)線程就可以讓CPU
跑到100%增热。
可以看到整以,只要在前一個(gè)線程一旦處于空閑時(shí)間中,后面的任務(wù)能夠立馬被執(zhí)行峻仇,線程就可以跑到100%公黑,如果單核
CPU
,線程工作2ms摄咆,阻塞時(shí)間為3ms凡蚜,那么我們就需要3個(gè)線程保證cpu跑到100%,所以線程數(shù)就是(執(zhí)行時(shí)間+空閑時(shí)間)/執(zhí)行時(shí)間
吭从,如果有小數(shù)朝蜘,那么就向上取整。所以如果是N
核CPU
涩金,最佳的設(shè)置的線程數(shù)是=N*((執(zhí)行時(shí)間+空閑時(shí)間)/執(zhí)行時(shí)間)
谱醇。所以在單機(jī)上,
rabbitmq
消費(fèi)者設(shè)置的合理并發(fā)數(shù)是:N*((消費(fèi)消費(fèi)時(shí)間+消息在網(wǎng)絡(luò)傳遞時(shí)間)/消費(fèi)消費(fèi)時(shí)間)