韋通明,張送,溫豐蔚,溫麗梅,張亮
(上汽通用五菱汽車股份有限公司技術(shù)中心,廣西 柳州545007)
隨著汽車智能網(wǎng)聯(lián)化的發(fā)展,汽車變得更加智能化的同時(shí),也產(chǎn)生更多的數(shù)據(jù)。在傳統(tǒng)的數(shù)據(jù)接收端中,數(shù)據(jù)的接收以及轉(zhuǎn)發(fā)都是阻塞式運(yùn)行,當(dāng)數(shù)據(jù)量大的時(shí)候,接收端可能卡死甚至宕機(jī)。接收端的宕機(jī)可能導(dǎo)致終端數(shù)據(jù)的丟失,會(huì)對(duì)公司造成重大的口碑和經(jīng)濟(jì)損失。因此,保證平臺(tái)平穩(wěn)而高效的運(yùn)行,對(duì)于智能網(wǎng)聯(lián)汽車平臺(tái)的重要性不言而喻。
使用 Netty作為數(shù)據(jù)平臺(tái)的接收端,在業(yè)界內(nèi)早已有人進(jìn)行了實(shí)踐,王鑫等[2]就提出了一種基于Netty作為基礎(chǔ)的數(shù)據(jù)通信框架;李熙、謝錦洋[3]也基于Netty和HDFS分布式文件系統(tǒng)設(shè)計(jì)出了一種大數(shù)據(jù)的接收以及采集系統(tǒng)。但是上面的兩個(gè)系統(tǒng)都是單純利用Netty接收和轉(zhuǎn)發(fā),Netty的Boss線程和Worker線程互相耦合,資源互相競(jìng)爭(zhēng),可能導(dǎo)致數(shù)據(jù)無法接受或者轉(zhuǎn)發(fā)[1],可能存在數(shù)據(jù)堆積等風(fēng)險(xiǎn)。
本文針對(duì)以上存在的不足,引入了Kafka消息中間件作為Netty的下游,使得Netty接收到的數(shù)據(jù)可以快速被轉(zhuǎn)發(fā)。Kafka被設(shè)計(jì)為能承受數(shù)十萬迸發(fā)的分布式消息中間件,能快速地緩存并且轉(zhuǎn)發(fā)數(shù)據(jù),減輕 Netty接收端的壓力。Kafka支持集群多副本部署,能夠防止數(shù)據(jù)丟失。我們將Netty與Kafka整合,能降低接收端集群的壓力,并且系統(tǒng)更加可靠。
Netty引用并優(yōu)化了JDK5引入的線程池技術(shù),并且修復(fù)了JDK原生NIO的BUG,并且將接收線程池與業(yè)務(wù)線程池進(jìn)行了分離。其中Acceptor線程池負(fù)責(zé)接受連接,worker線程池負(fù)責(zé)處理連接的讀寫事件。這種 Reactor模型的支持使得 Netty能用很少的連接就能處理大量的連接終端。同時(shí),Netty封裝了JDK NIO,簡(jiǎn)化了JDK NIO本身復(fù)雜的API,保留了安全性高、性能優(yōu)越等特點(diǎn)。Netty是個(gè)性能優(yōu)秀、使用簡(jiǎn)單的網(wǎng)絡(luò)通信框架,在本方案中,Netty專門負(fù)責(zé)接收終端連接請(qǐng)求。
Netty的線程模型如圖1所示:
圖1 Netty線程模型
Kafka作為隊(duì)列模式的消息中間件,能夠確保數(shù)據(jù)的順序性。Kafka的一個(gè)topic會(huì)由多個(gè)partition組成,每個(gè)partition還會(huì)有某個(gè)數(shù)量的副本,這些副本分散在Kafka的集群之中,一旦Kafka集群的某臺(tái)機(jī)器發(fā)生宕機(jī),可以從其他機(jī)器恢復(fù)副本數(shù)據(jù),從而保證數(shù)據(jù)的可靠性。Kafka的消息數(shù)據(jù)在一段時(shí)間內(nèi),即使被消費(fèi),也不會(huì)在分區(qū)和副本中刪除。Kafka與Netty使用了同樣的Zero-Copy零拷貝技術(shù),使用Send-file模式,可以直接在內(nèi)核態(tài)傳輸數(shù)據(jù),提升一倍的數(shù)據(jù)發(fā)送性能。
方案引入Kafka作為消息隊(duì)列,能夠高效、可靠地將數(shù)據(jù)進(jìn)行匯聚以及削峰填谷,極大地提升了集群的吞吐量和可靠性。
Kafka的模型如圖2:
圖2 Kafka架構(gòu)圖
在本方案之中,Netty作為與終端直連的數(shù)據(jù)接收端,負(fù)責(zé)接收外部鏈接請(qǐng)求,并且將終端上傳的數(shù)據(jù)轉(zhuǎn)發(fā)到 Kafka消息中間件之中。Netty接收端的數(shù)量可以根據(jù)終端數(shù)量動(dòng)態(tài)擴(kuò)容,始終滿足終端的需求。Kafka集群作為整個(gè)系統(tǒng)的緩沖池,接受從接收端轉(zhuǎn)發(fā)過來的流量,減輕接收端的壓力。Kafka提供緩存、冗余、負(fù)載均衡等能力,能保證consumer段始終能夠在最高效的狀態(tài)運(yùn)行。
整個(gè)系統(tǒng)的架構(gòu)如圖3所示:
圖3 系統(tǒng)架構(gòu)
為了驗(yàn)證方案的性能,本文搭建了一套壓力測(cè)試的環(huán)境。其中,CPU為十代i7-10700F,睿頻4.8 GHz,32G DDR4內(nèi)存,1T硬盤,操作系統(tǒng)為CentOS7,實(shí)驗(yàn)程序用Java編寫,JDK版本 jdk1.8.0_201,Netty的版本為 4.1.17-Final,Kafka的版本為 1.1.0。使用開源的壓測(cè)軟件 JMeter進(jìn)行模擬,模擬機(jī)器配置與服務(wù)端保持一致,并且部署在同一個(gè)局域網(wǎng)之中,局域網(wǎng)之間通過千兆網(wǎng)卡連接。測(cè)試終端模擬每秒發(fā)一次1KB的數(shù)據(jù)。
服務(wù)端分別使用傳統(tǒng)的 TcpSocket、原生 Netty以及Netty+Kafka實(shí)現(xiàn),客戶端并發(fā)規(guī)格為 2000、4000、6000、8000、10000、15000和20000個(gè)客戶端,壓測(cè)數(shù)據(jù)如圖4所示:
圖4 壓測(cè)數(shù)據(jù)
根據(jù)圖4,可以看出傳統(tǒng)的Tcp Socket在迸發(fā)8000左右的時(shí)候達(dá)到瓶頸,在客戶端迸發(fā)更大時(shí),服務(wù)端由于壓力過大,吞吐量反而下降;原生的Netty相比Socket吞吐量更高,但是隨迸發(fā)上升的趨勢(shì)不明顯;本方案吞吐量最高,性能也幾乎是線性增長(zhǎng),峰值的吞吐量達(dá)到了原生Netty的1.5倍。并且本方案支持緩沖以及數(shù)據(jù)冗余,可靠性更強(qiáng),更適合處理汽車數(shù)據(jù)這種高迸發(fā)的業(yè)務(wù)場(chǎng)景。
本文提出了一種整合Netty框架以及Kafka中間件的汽車大數(shù)據(jù)接收端的實(shí)現(xiàn)方案,并且分析了 Netty以及 Kafka在本方案之中的作用,二者是本方案能高效、穩(wěn)定運(yùn)行的基礎(chǔ)。本文還將本方案和傳統(tǒng)的方案進(jìn)行了性能對(duì)比,本方案的性能在并發(fā)量大時(shí),會(huì)有明顯的優(yōu)勢(shì)。本文提供樣例是單機(jī)部署的方案,在實(shí)際運(yùn)用的場(chǎng)景之中,只要將方案進(jìn)行集群化部署,就能支撐更多的終端、更大的并發(fā),具有很高的實(shí)際價(jià)值。