.NET Core使用IO合并技巧轻松实现千万级消息推送
之前講述過(guò)多路復(fù)用實(shí)現(xiàn)單服百萬(wàn)級(jí)別RPS吞吐,但在文中有一點(diǎn)是沒(méi)有說(shuō)的就是消息IO合并,如果缺少了消息IO合并即使怎樣多路復(fù)用也很難達(dá)到百萬(wàn)級(jí)別的請(qǐng)求響畢竟所有應(yīng)用層面的網(wǎng)絡(luò)IO讀寫(xiě)都是非常損耗性能的(需要硬件配置很高的服務(wù)器)。這一章主要講述的是IO合并的應(yīng)用,并通過(guò)這個(gè)特性實(shí)現(xiàn)普通單服務(wù)千萬(wàn)級(jí)別的消息推送測(cè)試。
什么是消息IO合并
所謂的消息IO合并即是由原來(lái)一個(gè)消息對(duì)應(yīng)一個(gè)網(wǎng)絡(luò)讀寫(xiě)設(shè)計(jì)成多個(gè)消息共享一個(gè)網(wǎng)絡(luò)讀寫(xiě)。那這樣的設(shè)計(jì)到底會(huì)帶來(lái)多大的性能提升,最簡(jiǎn)單的對(duì)比場(chǎng)就是每次執(zhí)行1條SQL執(zhí)行1萬(wàn)次和直接批執(zhí)行1萬(wàn)條SQL的差別,相信做過(guò)的朋友一定非常清楚其性能提升的幅度。那在網(wǎng)絡(luò)通訊中如何設(shè)計(jì)才能讓多個(gè)消息進(jìn)行IO合并呢?作者在實(shí)際實(shí)踐中的方式有兩種:1)通過(guò)定時(shí)器把隊(duì)列中的所有消息定期合并發(fā)送,2)通過(guò)一個(gè)狀態(tài)機(jī)歸遞消息隊(duì)列,一旦隊(duì)列存在消息一次過(guò)合并發(fā)送。定時(shí)器這種比較損耗性能,在連接量大的情況存在延時(shí)間相互影響;對(duì)于后者則比較好控制很多也不存在延時(shí)性,原理發(fā)送消息進(jìn)隊(duì)列后和網(wǎng)絡(luò)發(fā)送完成再回到狀態(tài)機(jī)檢測(cè)消息隊(duì)列狀態(tài)即可。?
消息推送相對(duì)于請(qǐng)求響應(yīng)來(lái)說(shuō)相還是簡(jiǎn)單很多的,畢竟消息推送是單向并不需要有高效的響應(yīng)機(jī)制。不過(guò)對(duì)于普通服務(wù)器間實(shí)現(xiàn)千萬(wàn)級(jí)的消息推送還是需要做些規(guī)劃,畢竟是需要在有限的IO讀寫(xiě)量的情況來(lái)達(dá)到這么大規(guī)模的消息處理。還有這么大量的消息序列化和反序列化也是一非常損耗性能的事情,所以這次實(shí)踐并沒(méi)有使用Protobuf,而是采用自定義序列化。測(cè)試的通訊組件選擇Beetlex因?yàn)樗邆淞俗詣?dòng)消息合并能力,并配合高效的多復(fù)路用機(jī)制在服務(wù)之間進(jìn)行千萬(wàn)級(jí)別的消息推變得簡(jiǎn)單。
測(cè)試簡(jiǎn)述
這一次測(cè)試主要是向服務(wù)端推著一個(gè)簡(jiǎn)單的訂單信息,由客戶(hù)每次生成不同的訂單信息推送給服務(wù)端,服務(wù)器接收訂單消息后進(jìn)行統(tǒng)計(jì),并計(jì)算每秒接收的訂單數(shù)量。
消息結(jié)構(gòu)
創(chuàng)建訂單
基于測(cè)試資源有限,這次的測(cè)試并沒(méi)像之前跑PRS那樣采用Protobuf,因?yàn)檫@量的對(duì)象處理量實(shí)在太大,測(cè)試的硬件環(huán)境不變所以采了自定義的序列化方式,具體可以參考源代碼。
接收端代碼
由于是接收推送的消息,服務(wù)端接收消息后統(tǒng)計(jì)相關(guān)數(shù)量即可完成,對(duì)于之前的RPS測(cè)試所需處理的東西就少很多了。
推送端壓測(cè)代碼
為了防止壓爆連接內(nèi)部的消息隊(duì)列,壓測(cè)端當(dāng)連接隊(duì)列超過(guò)2000個(gè)消息的時(shí)候停止一下。由于采用了消息合并機(jī)制所以并不需要太多連接,在整個(gè)測(cè)試過(guò)程中開(kāi)啟了三個(gè)壓測(cè)實(shí)例,每個(gè)實(shí)例使用5個(gè)連接,換句話(huà)說(shuō)BeetleX通過(guò)15個(gè)連接,實(shí)現(xiàn)千萬(wàn)級(jí)消息的推送能力。
測(cè)試服務(wù)器資源
這次測(cè)試使用了兩家云服務(wù)器,第一家名字就不說(shuō)了,開(kāi)啟了V16核的虛擬服務(wù)器,內(nèi)部帶寬6G和100萬(wàn)pps,結(jié)果實(shí)際壓測(cè)2G帶寬就壓不上去了,剛開(kāi)始以為是linux系統(tǒng)要配置問(wèn)題,換了windows系統(tǒng)試一下還是不行……,最終還是換回了阿里云測(cè),在v12核的虛擬服務(wù)器上順利完成了這一次測(cè)試。
服務(wù)端:?v12核,24G內(nèi)存,操作系統(tǒng)ubuntu16.04 一臺(tái),內(nèi)網(wǎng)最大帶寬4Gb.
壓測(cè)端:?v12核,24G內(nèi)存,操作系統(tǒng)ubuntu16.04,內(nèi)網(wǎng)最大帶寬4Gb, 兩臺(tái)(主要測(cè)試方式有些暴力一臺(tái)無(wú)法達(dá)到壓測(cè)目標(biāo))
測(cè)試結(jié)果
二臺(tái)壓測(cè)機(jī)共開(kāi)啟了3個(gè)實(shí)例,每個(gè)實(shí)例5個(gè)連接,每個(gè)連接應(yīng)用層處理的buffer 32k;整個(gè)測(cè)結(jié)果消息推送量達(dá)到了1000萬(wàn)個(gè)/秒。服務(wù)端記錄接收IO每秒15000次,平均每次receive得到的消息大概在600個(gè)左右。以下是測(cè)試情況的截圖:
服務(wù)程序統(tǒng)計(jì)情況
服務(wù)端CPU情況
網(wǎng)絡(luò)使用情況
下功測(cè)試代碼:?https://github.com/IKende/BeetleX/blob/master/samples/MassiveMessagepush.zip
原文地址:https://www.cnblogs.com/smark/p/9869384.html
.NET社區(qū)新聞,深度好文,歡迎訪(fǎng)問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com 
總結(jié)
以上是生活随笔為你收集整理的.NET Core使用IO合并技巧轻松实现千万级消息推送的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: IdentityServer4之JWT签
 - 下一篇: 一码阻塞,万码等待:ASP.NET Co