胡通
(中移(杭州)信息技術(shù)有限公司 浙江省杭州市 311121)
隨著移動(dòng)互聯(lián)網(wǎng)、5G 的飛速發(fā)展,高性能高并發(fā)的即時(shí)通信,有著非常廣泛的應(yīng)用場(chǎng)景,例如大家所熟知的微信聊天、大規(guī)模消息推送、視頻會(huì)議、直播彈幕、智能家居等,總之,一切高實(shí)時(shí)性要求的通訊場(chǎng)景,都需要高并發(fā)的即時(shí)通信。
中國(guó)移動(dòng)未來(lái)所有接入物聯(lián)網(wǎng)的智能家庭寬帶設(shè)備,都將是即時(shí)通信系統(tǒng)的客戶端,這就意味著推送服務(wù)未來(lái)會(huì)面臨海量的設(shè)備和終端接入。為了支持這些千萬(wàn)級(jí)、億級(jí)終端,一定是需要強(qiáng)悍的后臺(tái)系統(tǒng),而為了驗(yàn)證該后臺(tái)系統(tǒng)是否能支撐起如此龐大的家庭寬帶設(shè)備,需要進(jìn)行系統(tǒng)的性能測(cè)試,也就需要一種方法可以模擬這些百萬(wàn)、千萬(wàn)、億級(jí)的設(shè)備終端軟件測(cè)試工具。
目前,即時(shí)通信應(yīng)用大部分是基于WEBSOCKET 協(xié)議進(jìn)行開發(fā),而現(xiàn)有的主流性能測(cè)試工具(如LOADRUNNER、JMETER 等軟件),一方面對(duì)該協(xié)議支持的粒度不夠,無(wú)法滿足私有化的交互協(xié)議要求,另一方面由于其工具本身采用多線程的模式,模擬百萬(wàn)連接的資源消耗巨大,甚至無(wú)法勝任,因此,測(cè)試人員無(wú)法高效率地開展WEBSOCKET 協(xié)議類的性能測(cè)試。
如何針對(duì)基于WEBSOCKET 協(xié)議的即時(shí)通信應(yīng)用實(shí)施性能測(cè)試成為了軟件測(cè)試研究領(lǐng)域中亟待解決的問(wèn)題,在這個(gè)問(wèn)題的研究上既存在著機(jī)遇又充滿著挑戰(zhàn)。
基于以上研究討論,本文采用互聯(lián)網(wǎng)行業(yè)中一些高性能的框架和中間件,設(shè)計(jì)了一種WEBSOCKET 協(xié)議的性能測(cè)試工具模型,以彌補(bǔ)此類工具的空白。該方法主要借助于NETTY 的異步、事件驅(qū)動(dòng)的特性構(gòu)建高性能的客戶端性能測(cè)試工具,首先,通過(guò)自定義協(xié)議的編解碼,可以方便的實(shí)現(xiàn)移動(dòng)家寬寬帶設(shè)備協(xié)議數(shù)據(jù)的編碼和解碼,可擴(kuò)展性強(qiáng);另外,優(yōu)化改造池化技術(shù),重用連接,防止反復(fù)申請(qǐng)和釋放連接,提高連接的使用率和消息的收發(fā)能力;然后引入KAFKA 和REDIS 中間件,進(jìn)行性能指標(biāo)數(shù)據(jù)的匯總統(tǒng)計(jì);最后通過(guò)測(cè)試節(jié)點(diǎn)的自動(dòng)調(diào)度,靈活增加客戶端的并發(fā)能力,滿足更大規(guī)模場(chǎng)景的WEBSOCKET的性能測(cè)試需求。
WEBSOCKET 是一個(gè)獨(dú)立的基于TCP 的協(xié)議,是HTML5 新出的一個(gè)協(xié)議,與HTTP 協(xié)議具有一定的交集。在WEBSOCKET出現(xiàn)之前,網(wǎng)站為了實(shí)現(xiàn)即時(shí)的通信,都是采用輪詢拉取服務(wù)端的數(shù)據(jù),雖然這種方式可以完成類似于數(shù)據(jù)推送的通信,但是在即時(shí)性和性能上都不如WEBSOCKET 技術(shù)。
WEBSOCKET 在建立連接后允許客戶端和服務(wù)器之間進(jìn)行全雙工通信,以便任一方都可以通過(guò)建立的連接將數(shù)據(jù)推送到另一端。WEBSOCKET 只需要建立一次連接,就可以一直保持連接狀態(tài),這相比于輪詢方式的不停建立連接顯然效率要大大提高。
因此,WEBSOCKET 協(xié)議具有顯著的2 點(diǎn)特性:
圖1:總體設(shè)計(jì)圖
圖2:自定義消息
2.1.1 支持推送功能
支持服務(wù)器端向客戶端推送功能,服務(wù)器可以直接發(fā)送數(shù)據(jù)而不用等待客戶端的請(qǐng)求,實(shí)時(shí)性強(qiáng)。
2.1.2 減少通信量
只要建立起WEBSOCKET 連接,就一直保持連接,在此期間可以源源不斷地傳送消息,直到關(guān)閉請(qǐng)求,相比于HTTP,不但每次連接時(shí)的總開銷減少了,而且WEBSOCKET 的首部信息量也更小,通信的效率更高。
由于WEBSOCKET 連接與典型的HTTP 連接請(qǐng)求方式不同,因此其性能測(cè)試中關(guān)注的性能點(diǎn)也不一樣,結(jié)合日常的系統(tǒng)項(xiàng)目工程的應(yīng)用實(shí)踐,重點(diǎn)提煉了3 個(gè)性能點(diǎn)。
WEBSOCKET 性能測(cè)試的關(guān)注點(diǎn):
(1)系統(tǒng)可以瞬間創(chuàng)建長(zhǎng)連接的數(shù)目;
(2)系統(tǒng)可以長(zhǎng)時(shí)間支撐的長(zhǎng)連接數(shù)目;
(3)系統(tǒng)在保持一定的連接數(shù)下推送數(shù)據(jù)的速度。
與此相應(yīng)的,可以設(shè)計(jì)3 種典型的性能測(cè)試場(chǎng)景:
場(chǎng)景1:大量連接的創(chuàng)建,即不斷模擬大量用戶對(duì)被測(cè)系統(tǒng)WEBSOCKET 連接的創(chuàng)建過(guò)程。
場(chǎng)景2:長(zhǎng)時(shí)間穩(wěn)定保持大量連接,即按照一定速度創(chuàng)建連接,并通過(guò)心跳消息保持連接長(zhǎng)時(shí)間的處于連接狀態(tài)。
場(chǎng)景3:大量推送消息,即通過(guò)保持一定數(shù)目的長(zhǎng)連接,然后在各個(gè)連接通道上不斷觸發(fā)消息推送。
NETTY 是一款異步的事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用開源框架,用于快速開發(fā)可維護(hù)的高性能、高擴(kuò)展性協(xié)議服務(wù)器和客戶端。通常該框架應(yīng)用于服務(wù)端的開發(fā),而本文充分借助于該框架的高性能的能力設(shè)計(jì)了一個(gè)典型客戶端工具,應(yīng)用于WEBSOCKET 協(xié)議的性能測(cè)試。
該性能測(cè)試工具設(shè)計(jì)模型核心主要包括測(cè)試分布式調(diào)度、壓測(cè)節(jié)點(diǎn)、數(shù)據(jù)采集3 個(gè)模塊,如圖1所示。首先,測(cè)試分布式調(diào)度會(huì)根據(jù)測(cè)試任務(wù)規(guī)模級(jí)別信息自動(dòng)選擇可用的節(jié)點(diǎn)機(jī)器發(fā)起分布式的測(cè)試任務(wù),然后壓測(cè)節(jié)點(diǎn)借助于NETTY 的自定義編解碼方式,完成私有協(xié)議的數(shù)據(jù)解析;之后通過(guò)優(yōu)化配置池化和共享技術(shù)提升客戶端的建立連接的能力;最后數(shù)據(jù)采集通過(guò)REDIS 和KAFKA 中間件存儲(chǔ)統(tǒng)計(jì)器計(jì)算出連接數(shù)、發(fā)包速度、收包速度、丟包率等性能指標(biāo)。
若要模擬百萬(wàn)千萬(wàn)的大規(guī)模的性能測(cè)試要求,可以根據(jù)壓測(cè)節(jié)點(diǎn)機(jī)器的配置或資源結(jié)合一定的算法自動(dòng)分配不同壓測(cè)節(jié)點(diǎn)的壓測(cè)任務(wù)大小,然后再采用分布式的方式發(fā)起壓力。通過(guò)該方式,可以最大限度的發(fā)揮不同壓測(cè)節(jié)點(diǎn)的資源,提高壓力產(chǎn)生的能力,滿足大規(guī)模需求。
3.3.1 壓力產(chǎn)生器
壓力產(chǎn)生器采用SPRINGBOOT 技術(shù)作為服務(wù)框架,基于高性能網(wǎng)絡(luò)框架NETTY 進(jìn)行構(gòu)建,與NETTY 提供的線程模型進(jìn)行緊密結(jié)合。
基于NETTY 線程模型改造執(zhí)行線程池,任務(wù)執(zhí)行線程池維護(hù)一個(gè)多路復(fù)用的線程池,每個(gè)線程對(duì)應(yīng)多個(gè)連接,對(duì)應(yīng)NETTY框架中每個(gè)線程對(duì)應(yīng)多個(gè)CHANNEL,另外任務(wù)執(zhí)行線程池中還包括一個(gè)連接池,該連接池為基于線程池創(chuàng)建的CHANNEL 連接池,在初始化階段,為每個(gè)線程創(chuàng)建多個(gè)CHANNEL,并且這些CHANNEL 是可以復(fù)用的,當(dāng)一個(gè)實(shí)例被提交給一個(gè)線程時(shí),該線程為該實(shí)例分配一個(gè)可用的連接供使用。每個(gè)實(shí)例執(zhí)行時(shí)是非阻塞的,所以即使是單線程也可以達(dá)到較高的并發(fā)量。
通過(guò)優(yōu)化改造NIO 異步多線程模型,設(shè)定同一個(gè)EVENTLOOP會(huì)被多個(gè)CHANNEL 所共享,這使得可以通過(guò)盡可能少量的THREAD 來(lái)支撐大量的CHANNEL,而不是每個(gè)CHANNEL 分配一個(gè)THREAD,并結(jié)合多路復(fù)用器SECLTOR,使得少量資源即可模擬成千上萬(wàn)的移動(dòng)家寬寬設(shè)備客戶端。
3.3.2 自定義消息
移動(dòng)家庭寬帶設(shè)備采用自定義的WEBSOCKET 的協(xié)議進(jìn)行設(shè)備的登陸和數(shù)據(jù)的上報(bào),如圖2所示,采用5 個(gè)字節(jié)的消息頭和不定長(zhǎng)的消息體,其中消息頭包括開始標(biāo)志、消息類型和消息長(zhǎng)度,消息長(zhǎng)度代表消息體的大小。
本文采用NETTY 的自定義編解碼器,可以方便靈活的完成協(xié)議數(shù)據(jù)的交互,根據(jù)協(xié)議規(guī)定要求添加一個(gè)CHANNELHANDLER的編碼器和解碼器即可進(jìn)行消息的處理。
主要是通過(guò)NETTY 提供的LengthFieldPrepender 編碼器,自動(dòng)計(jì)算當(dāng)前待發(fā)送數(shù)據(jù)的長(zhǎng)度,并將該長(zhǎng)度添加到當(dāng)前數(shù)據(jù)的頭部形成待發(fā)送的完整數(shù)據(jù)楨。在接收數(shù)據(jù)的時(shí)候,使用的是LengthFieldBasedFrameDecoder 解碼器,通過(guò)該解碼器首先根據(jù)開始標(biāo)志和5 字節(jié)長(zhǎng)度自動(dòng)截取數(shù)據(jù)頭,并解析出消息類型和消息長(zhǎng)度,然后依據(jù)該消息長(zhǎng)度在此后截取消息體部分的字節(jié)流,解決數(shù)據(jù)傳輸過(guò)程中出現(xiàn)粘包問(wèn)題,完成數(shù)據(jù)解碼,保證數(shù)據(jù)的正確性和安全性,最后再交給專門的事務(wù)處理器HANDLER 進(jìn)行處理和響應(yīng)。
WEBSOCKET 長(zhǎng)連接的性能指標(biāo)數(shù)據(jù)不同于常見的HTTP 請(qǐng)求,性能關(guān)注點(diǎn)側(cè)重于連接數(shù)、收包速度、發(fā)包速度、丟包率等。另外,傳統(tǒng)的同步服務(wù)調(diào)用,發(fā)起服務(wù)調(diào)用之后,業(yè)務(wù)線程阻塞,等待響應(yīng),接收響應(yīng)之后,業(yè)務(wù)線程繼續(xù)執(zhí)行,對(duì)發(fā)送的消息進(jìn)行累加,獲取性能指標(biāo)數(shù)據(jù);而使用NETTY,所有的網(wǎng)絡(luò)I/O 操作都是異步執(zhí)行的,不能和同步執(zhí)行一樣計(jì)算性能指標(biāo)。
本文借助于REDIS 的原子性操作,匯總統(tǒng)計(jì)壓測(cè)節(jié)點(diǎn)建立的WEBSOCKET 連接個(gè)數(shù),避免臟寫。另外通過(guò)使用KAFKA 作為消息隊(duì)列來(lái)收集WEBSOCKET 長(zhǎng)連接收發(fā)的性能消息數(shù)據(jù),可以降低系統(tǒng)之間的耦合度。KAFKA 消息隊(duì)列方式可以控制消息消費(fèi)者消費(fèi)的速度,可以提高消息處理效率并避免由于消費(fèi)速度過(guò)慢導(dǎo)致消息堆積或消費(fèi)速度過(guò)快導(dǎo)致長(zhǎng)時(shí)間等待的情況。
另外,如果壓測(cè)節(jié)點(diǎn)存在多個(gè)共同參與施壓,則可以建立多個(gè)KAFKA 消息隊(duì)列,依次存放每個(gè)執(zhí)行節(jié)點(diǎn)單獨(dú)上報(bào)和接收的數(shù)據(jù),之后再進(jìn)行匯聚計(jì)算。
通過(guò)這個(gè)方式可以便捷地獲取壓測(cè)過(guò)程中的長(zhǎng)連接性能指標(biāo),觀察被測(cè)系統(tǒng)的穩(wěn)定性和狀態(tài)。
本文主要設(shè)計(jì)思路借鑒了很多開源框架的高性能設(shè)計(jì)原則,始終本著使用簡(jiǎn)單,低耦合和高內(nèi)聚的軟件設(shè)計(jì)思路進(jìn)行實(shí)現(xiàn),采用的都是通用插件式設(shè)計(jì),方便后續(xù)擴(kuò)展。
該性能測(cè)試工具設(shè)計(jì)模型通過(guò)優(yōu)化的池化和重用線程方式來(lái)消除由上下文切換所帶來(lái)的開銷,能夠適應(yīng)快速增長(zhǎng)的移動(dòng)設(shè)備的規(guī)模,可以在保持服務(wù)資源低成本的同時(shí),模擬更大量的家庭寬帶設(shè)備,伸縮能力強(qiáng)。
并且,利用NETTY 自定義編解碼器,能夠高效地完成移動(dòng)家庭寬帶設(shè)備的WEBSOCKET 協(xié)議的自定義數(shù)據(jù)交互,靈活性高。
最后,結(jié)合高性能中間件REDIS 和KAFKA,采集、統(tǒng)計(jì)分析出WEBSOCKET 長(zhǎng)連接的連接數(shù)、發(fā)包速度、收包速度等特殊的性能指標(biāo),彌補(bǔ)了WEBSOCKET 長(zhǎng)連接協(xié)議無(wú)法有效開展性能測(cè)試的技術(shù)空白,豐富了性能測(cè)試手段和方式。