楊怡濱 楊 偉 于新容 丘偉森
(廣東省輕工業(yè)高級(jí)技工學(xué)校信息工程系 廣東 廣州 510315)
服務(wù)網(wǎng)格[1]是致力于解決服務(wù)間通信的基礎(chǔ)設(shè)施層,負(fù)責(zé)在構(gòu)成復(fù)雜應(yīng)用系統(tǒng)的微服務(wù)間靈活、高效和可靠地傳遞請(qǐng)求,用于控制和監(jiān)視微服務(wù)應(yīng)用的內(nèi)部、服務(wù)到服務(wù)的通信。
服務(wù)網(wǎng)格由數(shù)據(jù)面和控制面組成,其中控制面用于集中設(shè)置相關(guān)策略進(jìn)行服務(wù)間交互的流量監(jiān)控與控制策略實(shí)施,而數(shù)據(jù)面則由一組輕量級(jí)網(wǎng)絡(luò)代理(簡(jiǎn)稱邊車代理)構(gòu)成。邊車代理是一個(gè)輔助進(jìn)程,它與主應(yīng)用程序一起運(yùn)行,并為其提供額外的功能。每個(gè)服務(wù)都配備了一個(gè)邊車代理,它們與微服務(wù)一起部署用來(lái)實(shí)現(xiàn)(即邊車部署模式)服務(wù)間的交互。
服務(wù)網(wǎng)格將服務(wù)間通信從底層的基礎(chǔ)設(shè)施中分離出來(lái)使得服務(wù)能夠被監(jiān)控、托管和控制,同時(shí)為服務(wù)運(yùn)行時(shí)提供統(tǒng)一的、應(yīng)用層面的可見性和可控性,因此有效解決了大規(guī)模微服務(wù)服務(wù)治理問題。
目前服務(wù)網(wǎng)格技術(shù)仍處于發(fā)展階段,性能是服務(wù)網(wǎng)格面臨的核心問題和挑戰(zhàn)[2]。服務(wù)網(wǎng)格(尤其是邊車代理)的加入會(huì)增加請(qǐng)求調(diào)用鏈路的長(zhǎng)度,因此必然會(huì)帶來(lái)性能的損耗。眾所周知,服務(wù)架構(gòu)多用于分布式互聯(lián)網(wǎng)系統(tǒng)應(yīng)用中,而來(lái)自客戶端的高并發(fā)訪問請(qǐng)求(如車票預(yù)訂、搶紅包、雙十一購(gòu)物節(jié)等場(chǎng)景)十分常見,在使用服務(wù)網(wǎng)格后,并發(fā)壓力從應(yīng)用層服務(wù)轉(zhuǎn)移到服務(wù)網(wǎng)格層面。因此,如何使服務(wù)網(wǎng)格具備高性能的、異步無(wú)阻塞的通信交互能力十分重要。本文分析發(fā)現(xiàn),影響服務(wù)網(wǎng)格整體性能的主要因素如下:(1) 服務(wù)網(wǎng)格數(shù)據(jù)面中的邊車代理負(fù)責(zé)服務(wù)間通信,在代理請(qǐng)求、向外轉(zhuǎn)發(fā)請(qǐng)求和回傳響應(yīng)三個(gè)關(guān)鍵步驟涉及大量網(wǎng)絡(luò)IO和計(jì)算,在高并發(fā)場(chǎng)景下使用大量線程資源,頻繁的線程切換會(huì)嚴(yán)重影響并發(fā)性能。(2) 服務(wù)間及邊車代理間交互通?;贖TTP協(xié)議,而傳統(tǒng)的HTTP協(xié)議具有固定的消息格式,其中可能包含冗余的數(shù)據(jù),其次HTTP協(xié)議基于TCP協(xié)議,因此每次請(qǐng)求建立連接時(shí)都經(jīng)歷三次握手,在高并發(fā)的場(chǎng)景下可能會(huì)造成明顯的延遲。
針對(duì)上述問題,本文提出了面向服務(wù)網(wǎng)格的性能優(yōu)化方法,首先基于Reactor模式[3],同時(shí)結(jié)合線程和協(xié)程[4]兩者的計(jì)算優(yōu)勢(shì),設(shè)計(jì)了一種具有高并發(fā)處理能力的計(jì)算模型,并將其用于邊車代理的設(shè)計(jì)實(shí)現(xiàn);其次基于HTTP協(xié)議設(shè)計(jì)了一種輕量、高效的應(yīng)用層交互協(xié)議,用以減少服務(wù)邊車代理間通信時(shí)傳輸?shù)臄?shù)據(jù)量,同時(shí)實(shí)現(xiàn)了基于零拷貝技術(shù)[5]的協(xié)議消息編解碼算法,可以顯著提高通信能力。
本文基于上述技術(shù)設(shè)計(jì)實(shí)現(xiàn)了一個(gè)原型系統(tǒng),并通過實(shí)驗(yàn)與當(dāng)前主流的服務(wù)網(wǎng)格系統(tǒng)Linkerd和Envoy進(jìn)行了對(duì)比。實(shí)驗(yàn)分別從并發(fā)性能和通信性能兩方面進(jìn)行分析比較,結(jié)果表明本文提出的優(yōu)化方法使得服務(wù)網(wǎng)格系統(tǒng)在減少響應(yīng)時(shí)間和網(wǎng)絡(luò)傳輸數(shù)據(jù)量?jī)煞矫婢酗@著的性能提升。
服務(wù)網(wǎng)格是近兩年興起的技術(shù),其相關(guān)研究目前較少,但是已經(jīng)得到了工業(yè)界的廣泛關(guān)注和應(yīng)用。Linkerd和Envoy是目前典型的服務(wù)網(wǎng)格系統(tǒng),Linkerd從2016年到2018年圍繞性能優(yōu)化發(fā)布了1.0.x、1.1.x、1.2.x、1.3.x、1.4.x、1.5.x、1.6.x等版本,嘗試使用最新版本的Finagle框架優(yōu)化、使用GraalVM提高性能、通過Open J9 JVM的支持降低40%的內(nèi)存占用并大幅降低長(zhǎng)尾延遲,目前GraalVM性能優(yōu)化方案失敗,僅存Open J9 JVM的優(yōu)化版本,其測(cè)試版本還在繼續(xù)發(fā)行。Envoy在2017年到2018年發(fā)布了1.2.x、1.3.x、1.4.x、1.5.x、1.6.x、1.7.x、1.8.x等版本,從多線程加非阻塞異步IO計(jì)算模型、通信協(xié)議優(yōu)化和熱重啟等方面進(jìn)行了優(yōu)化設(shè)計(jì)。
國(guó)內(nèi)自2017年底大規(guī)模開展高性能服務(wù)網(wǎng)格技術(shù)的研發(fā),其中:華為用Go語(yǔ)言在路由管理、多協(xié)議支持方面做優(yōu)化,自行開發(fā)了Mesher;螞蟻金服從IO、協(xié)議、調(diào)度策略方面對(duì)服務(wù)網(wǎng)格進(jìn)行了優(yōu)化并開發(fā)了SOFAMesh;新浪開發(fā)的WeiboMesh在通信方面提供HTTP Mesh方案,支持HTTP與RPC服務(wù)之間的交互。但是,服務(wù)網(wǎng)格的加入增加了請(qǐng)求調(diào)用鏈路的長(zhǎng)度,必然帶來(lái)性能的損耗,例如:阿里巴巴對(duì)基于Envoy自主開發(fā)的Dubbo Mesh進(jìn)行測(cè)試,發(fā)現(xiàn)Dubbo Mesh的每一次請(qǐng)求轉(zhuǎn)發(fā)會(huì)造成1.5 ms的延時(shí)。
與上述工作不同,本文主要從并發(fā)處理模型和服務(wù)網(wǎng)格數(shù)據(jù)傳輸兩方面提出性能優(yōu)化的方法。
基于線程的并發(fā)和事件驅(qū)動(dòng)是并發(fā)處理的兩種基本方法。迄今為止,事件驅(qū)動(dòng)的并發(fā)方法因其更高的性能和更好的可伸縮性而得到更為廣泛的應(yīng)用。Reactor模式是當(dāng)前具有代表性的事件驅(qū)動(dòng)的并發(fā)處理模式之一,常用于具有高并發(fā)需求的客戶端-服務(wù)器系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)中,許多流行的開源框架和服務(wù)器系統(tǒng)均基于Reactor模式,如Netty、Redis和Node.js等。
Reactor模式[3]稱為反應(yīng)器模式,是一種為處理并發(fā)服務(wù)請(qǐng)求,并將請(qǐng)求提交到一個(gè)或者多個(gè)服務(wù)處理程序的事件驅(qū)動(dòng)并發(fā)處理設(shè)計(jì)模式。當(dāng)客戶端請(qǐng)求抵達(dá)后,服務(wù)處理程序使用多路分配策略,由一個(gè)非阻塞線程來(lái)接收所有的請(qǐng)求,然后派發(fā)這些請(qǐng)求至相關(guān)的工作線程進(jìn)行處理。Reactor模式主要包含如下四部分內(nèi)容。
(1) 初始事件分發(fā)器(Initialization Dispatcher)用于管理事件處理器(Event Handler),負(fù)責(zé)定義注冊(cè)、移除事件處理器等。當(dāng)服務(wù)請(qǐng)求到達(dá)時(shí),它根據(jù)事件發(fā)生的Handle將其分發(fā)給對(duì)應(yīng)的事件處理器進(jìn)行處理。
(2) 同步(多路)事件分離器(Synchronous Event Demultiplexer)無(wú)限循環(huán)等待新事件的到來(lái),一旦發(fā)現(xiàn)有新的事件到來(lái),就會(huì)通知初始事件分發(fā)器去調(diào)取特定的事件處理器。
(3) 系統(tǒng)處理程序(Handles)是操作系統(tǒng)中的句柄,是對(duì)資源在操作系統(tǒng)層面上的一種抽象,它可以是打開的文件、一個(gè)連接(Socket)、時(shí)鐘等。由于Reactor模式一般使用在網(wǎng)絡(luò)編程中,因而這里一般指Socket Handle,即一個(gè)網(wǎng)絡(luò)連接(Connection Channel)注冊(cè)到同步(多路)事件分離器中,以監(jiān)聽Handle中發(fā)生的事件,包括網(wǎng)絡(luò)連接事件、讀/寫和關(guān)閉事件等。
(4) 事件處理器(Event Handler)用來(lái)定義事件處理方法,以供初始事件分發(fā)器回調(diào)使用。
對(duì)于高并發(fā)系統(tǒng),常會(huì)使用Reactor模式,其代替了常用的多線程處理方式,節(jié)省了系統(tǒng)的資源,提高了系統(tǒng)的吞吐量。由于服務(wù)網(wǎng)格系統(tǒng)作為服務(wù)間交互的基礎(chǔ)設(shè)施層常常面臨服務(wù)請(qǐng)求與響應(yīng)的高并發(fā)場(chǎng)景,因此本文選擇基于Reactor模式進(jìn)行服務(wù)網(wǎng)格中邊車代理并發(fā)處理模型的設(shè)計(jì)。本文對(duì)Reactor模式進(jìn)行了擴(kuò)展,結(jié)合線程和協(xié)程的各自優(yōu)勢(shì),實(shí)現(xiàn)由Manager、Worker和Collaborator三類角色協(xié)同的高并發(fā)處理機(jī)制。
服務(wù)網(wǎng)格的典型工作模式如圖1所示。以單方面的Microservice A的視角為例:Microservice A的服務(wù)網(wǎng)格組件邊車(Mesh A)代理Microservice A對(duì)Microservice B的網(wǎng)絡(luò)通信,Mesh A一方面需要維護(hù)與Microservice A的連接,另一方面需要將Microservice A的請(qǐng)求數(shù)據(jù)轉(zhuǎn)發(fā)給Microservice B(Microservice B的網(wǎng)絡(luò)通信由Mesh B代理),然后Mesh A收到響應(yīng)并回傳給Microservice A。
圖1 服務(wù)網(wǎng)格工作模式
在Microservice A通信的過程中,Mesh A充當(dāng)了類似“Server”與“Client”的角色,其中的計(jì)算過程可以分解成代理請(qǐng)求、向外轉(zhuǎn)發(fā)請(qǐng)求和回傳響應(yīng)三個(gè)關(guān)鍵步驟。由于Reactor模型通常用于服務(wù)器端的設(shè)計(jì),而每個(gè)服務(wù)網(wǎng)格的組件邊車代理在圖1所示的工作模式中都會(huì)承擔(dān)“Server”的角色,基于這一觀察分析,本文提出了基于Reactor模式的并發(fā)計(jì)算模型,用于設(shè)計(jì)構(gòu)成服務(wù)網(wǎng)格數(shù)據(jù)面的邊車代理。
如圖2所示,該模型分為Manager、Worker和Collaborator三種角色。Manager以線程作為計(jì)算實(shí)體運(yùn)行,用于維護(hù)服務(wù)的連接及分發(fā)連接的網(wǎng)絡(luò)事件給Worker;Worker同樣以線程作為計(jì)算實(shí)體運(yùn)行,Worker執(zhí)行相關(guān)數(shù)據(jù)計(jì)算的任務(wù),然后通過Collaborator向外轉(zhuǎn)發(fā)請(qǐng)求;Collaborator以協(xié)程作為計(jì)算實(shí)體運(yùn)行,轉(zhuǎn)發(fā)請(qǐng)求并等待、計(jì)算、處理和回傳響應(yīng)。由圖2可以看出Manager和Worker基于Reactor模式,而Collaborator則是在Reactor模式上的進(jìn)一步擴(kuò)展。
圖2 基于Reactor的高并發(fā)計(jì)算模型
Manager和Worker基于Reactor模式設(shè)計(jì)實(shí)現(xiàn),傳統(tǒng)的順序編程采用每條指令依次執(zhí)行的方式,難以滿足高性能的需求。Reactor模式是基于數(shù)據(jù)流和變化傳遞的聲明式的編程范式,用消息發(fā)送的事件流驅(qū)動(dòng)機(jī)制取代傳統(tǒng)的順序執(zhí)行機(jī)制[6]。Manager和Worker服務(wù)的請(qǐng)求數(shù)據(jù)作為數(shù)據(jù)流,Manager建立、維護(hù)相關(guān)連接后不會(huì)阻塞消息處理,Manager會(huì)監(jiān)聽各種網(wǎng)絡(luò)事件并分發(fā)給相應(yīng)的Worker進(jìn)行處理。
服務(wù)網(wǎng)格啟動(dòng)時(shí),綁定操作系統(tǒng)的某個(gè)端口后,首先將套接字(Socket)注冊(cè)到Manager線程的選擇器(Selector)上。Manager負(fù)責(zé)維護(hù)連接上下文的一致性,通過Selector監(jiān)聽客戶端的TCP連接請(qǐng)求,并將消息的數(shù)據(jù)流事件循環(huán)(EventLoop)調(diào)度給相應(yīng)的Worker進(jìn)行處理。Worker負(fù)責(zé)消息的讀取、解碼、編碼和發(fā)送,Worker采用串行化設(shè)計(jì),1個(gè)Worker線程可以同時(shí)處理N條鏈路連接,1條鏈路只對(duì)應(yīng)1個(gè)Worker線程,通過串行化設(shè)計(jì)有效防止并發(fā)操作問題。
隨后,Worker和Collaborator協(xié)作,應(yīng)用于服務(wù)網(wǎng)格向外轉(zhuǎn)發(fā)請(qǐng)求和回傳響應(yīng)的場(chǎng)景。Worker通過scheduler調(diào)度器調(diào)度Collaborator執(zhí)行任務(wù),Collaborator協(xié)程執(zhí)行完任務(wù)后會(huì)動(dòng)態(tài)從其他的任務(wù)隊(duì)列偷取任務(wù)執(zhí)行。Collaborator負(fù)責(zé)請(qǐng)求轉(zhuǎn)發(fā)和響應(yīng)回傳等任務(wù),ClientChannel是轉(zhuǎn)發(fā)請(qǐng)求時(shí)與目標(biāo)服務(wù)的連接管道,Messenger執(zhí)行ClientChannel的讀、寫、解碼、編碼、轉(zhuǎn)發(fā)等,ServerChannel是與代理服務(wù)的連接,Messenger回傳響應(yīng)時(shí),將數(shù)據(jù)寫入ServerChannel。與Worker不同,1個(gè)Collaborator處理1條鏈路連接,1個(gè)鏈路對(duì)應(yīng)1個(gè)Collaborator協(xié)程。Collaborator由Worker觸發(fā)scheduler調(diào)度,Worker的事件循環(huán)組可包含多個(gè)事件循環(huán),每個(gè)事件循環(huán)包含1個(gè)選擇器和1個(gè)事件循環(huán)線程,每個(gè)事件循環(huán)線程通過事件機(jī)制向scheduler調(diào)度器調(diào)度Collaborator。
Collaborator基于協(xié)程實(shí)現(xiàn)。對(duì)比線程,協(xié)程有以下優(yōu)勢(shì):(1) 更好地利用CPU資源,沒有類似線程調(diào)度的上下文切換;(2) 更好地利用內(nèi)存資源,用戶只需要分配合適的空間即可。因此能夠避免頻繁的線程切換和由此導(dǎo)致的因CPU緩存行失效引起的性能下降問題。
為了減少服務(wù)網(wǎng)格中代理間傳輸?shù)臄?shù)據(jù)量,減輕網(wǎng)絡(luò)負(fù)載,本文基于HTTP協(xié)議進(jìn)行了通信協(xié)議的定制化,設(shè)計(jì)了輕量化的協(xié)議和相應(yīng)的編解碼算法,能夠有效降低服務(wù)代理交互的通信數(shù)據(jù)量,提高編解碼速率。
如圖3所示,定制化協(xié)議的結(jié)構(gòu)由固定長(zhǎng)度的消息頭Head(8字節(jié))和不定長(zhǎng)度的消息體組成,具體組成如下:Magic Number:表示是否該協(xié)議的數(shù)據(jù)包;Serial ID:表示標(biāo)志請(qǐng)求的序列號(hào);Event Type:表示事件類型,1表示心跳消息,0表示不是心跳消息;Response:返回?cái)?shù)據(jù),0表示服務(wù)端可以不作應(yīng)答,1表示服務(wù)端必須應(yīng)答消息;Message Type:表示請(qǐng)求或響應(yīng)的消息狀態(tài);Response Code:請(qǐng)求響應(yīng)狀態(tài)碼,200表示成功,400表示失敗,每種狀態(tài)碼對(duì)應(yīng)相關(guān)原因;Message Length:表示消息長(zhǎng)度;Message Body:表示消息數(shù)據(jù)。
圖3 定制化協(xié)議數(shù)據(jù)結(jié)構(gòu)
本文設(shè)計(jì)的編解碼算法主要解決網(wǎng)絡(luò)傳輸過程中出現(xiàn)的半包/粘包問題,同時(shí)基于零拷貝技術(shù)有效減少操作系統(tǒng)內(nèi)核態(tài)切換用戶態(tài)過程的性能損失。
如圖4所示,客戶端發(fā)送Msg1和Msg2兩個(gè)數(shù)據(jù)包給服務(wù)端,網(wǎng)絡(luò)通信過程中會(huì)出現(xiàn)以下問題:(1) 無(wú)半包、無(wú)粘包,即服務(wù)端依次收到兩個(gè)獨(dú)立完整的數(shù)據(jù)包;(2) 半包,即服務(wù)端收到一個(gè)數(shù)據(jù)包,數(shù)據(jù)包只包含了Msg1的一部分;(3) 粘包,即服務(wù)端收到一個(gè)數(shù)據(jù)包,數(shù)據(jù)包包含了兩個(gè)請(qǐng)求的數(shù)據(jù)。
圖4 半包和粘包
基于上述情況,本文設(shè)計(jì)了一個(gè)基于計(jì)數(shù)的可彈性伸縮的鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)BufferLinkList,用以緩存網(wǎng)絡(luò)交互數(shù)據(jù),并進(jìn)行編解碼。BufferLinkList底層是循環(huán)鏈表,由Buffer塊構(gòu)成,Buffer塊封裝了直接內(nèi)存,可以指定大小,默認(rèn)為64字節(jié),RefCnt表示Buffer的引用計(jì)數(shù),通過引用計(jì)數(shù),系統(tǒng)會(huì)自動(dòng)進(jìn)行垃圾回收。BufferLinkList能夠彈性伸縮,如果數(shù)據(jù)過多,BufferLinkList會(huì)自動(dòng)擴(kuò)容,如果數(shù)據(jù)過少,會(huì)自動(dòng)縮容。基于BufferLinkList的零拷貝體現(xiàn)在以下方面:(1) 在直接內(nèi)存里面分配空間,而不是在堆內(nèi)存中分配;(2) BufferLink-List會(huì)自動(dòng)增減Buffer塊,對(duì)上層提供統(tǒng)一讀寫接口,避免了數(shù)據(jù)的拷貝。BufferLinkList的數(shù)據(jù)結(jié)構(gòu)如圖5所示。
圖5 BufferLinkList數(shù)據(jù)結(jié)構(gòu)
編碼時(shí),首先計(jì)算數(shù)據(jù)包的大?。蝗缓蟾鶕?jù)協(xié)議數(shù)據(jù)結(jié)構(gòu)編碼并存儲(chǔ)到BufferLinkList中;最后通知操作系統(tǒng)發(fā)送網(wǎng)絡(luò)數(shù)據(jù)。編碼算法如算法1所示。
算法1編碼算法
輸入:data。
輸出:bufferLinkList。
1. size←caculateSize(data)
//計(jì)算數(shù)據(jù)包大小
2. bufferLinkList←ButfferLinkListPool.getBufferLinkList(size)
//申請(qǐng)鏈表
3. header←HeaderTemplate.getHeader()
//從模板初始化頭部數(shù)據(jù)
4. header.setMagic(MAGIC)
//用戶自定義配置
5. header.setld(ID)
6. header.setlsHeartBeat(false)
7. head.setLength(data,length)
8. ……
9. bufferLinkList.write(head,data)
//寫入數(shù)據(jù)
10. bufferLinkList.setRefCnt(1)
11.returnbufferLinkList
EndFunction
解碼時(shí),首先用BufferLinkList緩存操作系統(tǒng)收到的網(wǎng)絡(luò)數(shù)據(jù);然后根據(jù)已緩存數(shù)據(jù)的大小判斷是否滿足Head解碼階段,如果滿足則進(jìn)入Head解碼,如果不滿足則繼續(xù)緩存;完成Head解碼后計(jì)算消息的長(zhǎng)度并進(jìn)入Body解碼狀態(tài),如果網(wǎng)絡(luò)數(shù)據(jù)大于等于消息長(zhǎng)度則執(zhí)行完解碼過程,并對(duì)已解碼的數(shù)據(jù)重置引用計(jì)數(shù),否則繼續(xù)緩存,等待下一個(gè)Body解碼狀態(tài)。解碼算法如算法2所示。
算法2解碼算法
輸入:bufferLinkList。
輸出:data。
1. decodeStat←State.Head
//初始化解碼狀態(tài)
2. length←0
3.whilebufferLinkList←receive_data()do
4.ifdecodeState==State.Headthen
//判斷解碼階段
5.ifbufferLinkList.size()<32then
6.continue
//數(shù)據(jù)不足,跳出
7.else
8. length←bufferLinkList.getDataBodyLength()
9. decodeState←State.Body
//進(jìn)入Body解碼階段
10.ifbufferLinkList.size() -32>=lengththen
11.gotoGetData
12.else
13.continue
14.endif
15.endif
16.elseifdecodeState==State.Body
17.ifbufferLinkList.size() -32 18.continue //數(shù)據(jù)不足,跳出 19.else 20. GetData: data←bufferLinkList.getData(length) //獲取數(shù)據(jù)體 21. endIndex←bufferLinkL ist.startIndex+length+32 //應(yīng)用計(jì)數(shù)重置 22. bufferLinkList.setRefCnt(startIndex,endIndex,0) 23. bufferLinkList.setStartIndex(endlndex) //指正清零 24.returndata 25.endif 26.endif 27.endwhile EndFunction 基于上述關(guān)鍵技術(shù),本文基于Java 8設(shè)計(jì)實(shí)現(xiàn)了一個(gè)原型系統(tǒng)如圖6所示。整個(gè)系架構(gòu)采用分層模型設(shè)計(jì),包括核心層、計(jì)算層、應(yīng)用層。 圖6 原型系統(tǒng)總體架構(gòu) 1) 核心層:包括BufferLinkListPool和統(tǒng)一通信接口。BufferLinkListPool提供BufferLinkList,BufferLinkList是封裝了直接內(nèi)存的鏈?zhǔn)浇Y(jié)構(gòu),用于緩存網(wǎng)絡(luò)IO數(shù)據(jù),支持基于計(jì)數(shù)的垃圾回收,并且彈性可伸縮;統(tǒng)一通信API層提供了基于BufferLinkList的通信相關(guān)的操作接口。 2) 計(jì)算層:提供了以線程封裝的Manager、Worker等計(jì)算資源及用協(xié)程封裝的Messenger計(jì)算資源,基于本文提出的并發(fā)處理模型提供高并發(fā)處理能力。 3) 應(yīng)用層:實(shí)現(xiàn)了服務(wù)網(wǎng)格的核心服務(wù),如:服務(wù)注冊(cè)與發(fā)現(xiàn)服務(wù)、協(xié)議與編解碼服務(wù)、路由選取服務(wù)等。 網(wǎng)絡(luò)數(shù)據(jù)進(jìn)入服務(wù)網(wǎng)格后的處理流程包括以下步驟:(1) 網(wǎng)絡(luò)數(shù)據(jù)從物理網(wǎng)卡進(jìn)入,操作系統(tǒng)陷入內(nèi)核態(tài)處理;(2) 服務(wù)網(wǎng)格從BufferLinkListPool獲取BufferLinkList,并緩存IO數(shù)據(jù);(3) 使用反應(yīng)式編程的BWM計(jì)算模型的計(jì)算資源,Manager線程維護(hù)連接,并向Worker線程分發(fā)任務(wù);(4) Worker線程通過統(tǒng)一通信API處理相關(guān)數(shù)據(jù),如編解碼,然后分發(fā)給Collaborator協(xié)程,并重新編碼向外轉(zhuǎn)發(fā);(5) Collaborator收到請(qǐng)求后回傳給代理服務(wù)。 為了評(píng)價(jià)本文方法的有效性,本節(jié)首先設(shè)計(jì)相關(guān)實(shí)驗(yàn),將原型系統(tǒng)(簡(jiǎn)稱BWM)與目前主流服務(wù)網(wǎng)格系統(tǒng)Linkerd(1.6版本)和Envoy(1.8版本)在相同環(huán)境下進(jìn)行性能測(cè)試。實(shí)驗(yàn)環(huán)境基于2臺(tái)阿里云服務(wù)器搭建,每臺(tái)服務(wù)器配置信息如圖7所示,并根據(jù)實(shí)驗(yàn)結(jié)果進(jìn)行分析對(duì)比。 圖7 實(shí)驗(yàn)環(huán)境設(shè)計(jì) 實(shí)驗(yàn)由施壓方和受壓方組成,施壓方Benchmarker會(huì)產(chǎn)生三組高并發(fā)連接(128并發(fā)連接、256并發(fā)連接和512并發(fā)連接)向Cosumer服務(wù)進(jìn)行壓測(cè),Benchmarker生成隨機(jī)的字符串data并發(fā)送請(qǐng)求給Cosumer服務(wù),Cosumer服務(wù)收到該請(qǐng)求后會(huì)通過服務(wù)網(wǎng)格將data發(fā)給Provider服務(wù)的服務(wù)網(wǎng)格,Provider服務(wù)的服務(wù)網(wǎng)格將data發(fā)給Provider服務(wù),Provider服務(wù)計(jì)算data的HashCode后將HashCode(data)通過服務(wù)網(wǎng)格返回Cosumer服務(wù)的服務(wù)網(wǎng)格,Cosumer服務(wù)的服務(wù)網(wǎng)格將響應(yīng)返回給Cosumer服務(wù),Cosumer服務(wù)最后將結(jié)果返回給Benchmarker校驗(yàn)并統(tǒng)計(jì)相關(guān)性能指標(biāo)。 實(shí)驗(yàn)時(shí)每一組壓力測(cè)試持續(xù)時(shí)間60 s,運(yùn)行10次,去掉最好和最差的實(shí)驗(yàn)數(shù)據(jù),最終的實(shí)驗(yàn)數(shù)據(jù)取平均值。實(shí)驗(yàn)流程如下: (1) 每輪評(píng)測(cè)在受壓方中啟動(dòng)五個(gè)服務(wù)(以Docker實(shí)例的形式啟動(dòng)),一個(gè)ETCD服務(wù)作為注冊(cè)表、一個(gè)Consumer服務(wù)和三個(gè)Provider服務(wù),每個(gè)服務(wù)都會(huì)綁定服務(wù)網(wǎng)格,Provider服務(wù)會(huì)Sleep(50 ms)模擬計(jì)算時(shí)間; (2) 使用另一臺(tái)獨(dú)立的服務(wù)器作為施壓方,分不同壓力場(chǎng)景對(duì)Consumer服務(wù)進(jìn)行壓力測(cè)試,得到相關(guān)性能指標(biāo); (3) ETCD是注冊(cè)中心服務(wù),用來(lái)存儲(chǔ)服務(wù)注冊(cè)信息;Provider是服務(wù)提供者,Consumer是服務(wù)消費(fèi)者,Consumer消費(fèi)Provider提供的服務(wù)。 為了盡可能模擬真實(shí)情況,每個(gè)服務(wù)實(shí)例所占用的系統(tǒng)資源各不相同,運(yùn)行Consumer服務(wù)及其Service Mesh的實(shí)例(為了便于描述,下文將簡(jiǎn)稱為Consumer實(shí)例,Provider實(shí)例類似)占用的系統(tǒng)資源是最多的,而三個(gè)Provider實(shí)例占用的系統(tǒng)資源總和與Consumer實(shí)例占用的系統(tǒng)資源是相同的,并且Provider實(shí)例按照small ∶medium ∶large=1 ∶2 ∶3的比例進(jìn)行分配,分為Provider(small)實(shí)例、Provider(medium)實(shí)例和Provider(large)實(shí)例,服務(wù)實(shí)例的資源分配如表1所示。 表1 服務(wù)實(shí)例資源分配 在每個(gè)Consumer和Provider實(shí)例中,都存在一個(gè)服務(wù)網(wǎng)格實(shí)例,其在整個(gè)系統(tǒng)中起到了非常關(guān)鍵的作用。 (1) Consumer服務(wù)是基于Spring Cloud實(shí)現(xiàn)的Web應(yīng)用,會(huì)發(fā)送請(qǐng)求給Provider服務(wù),服務(wù)之間數(shù)據(jù)傳遞是通過服務(wù)網(wǎng)格進(jìn)行的,服務(wù)網(wǎng)格的性能決定了系統(tǒng)的性能;(2) 任何一個(gè)Provider實(shí)例的性能都是小于Consumer實(shí)例的,服務(wù)實(shí)例的調(diào)度選取策略意義重大;(3) Provider實(shí)例最高支持200并發(fā)的連接,高并發(fā)下會(huì)產(chǎn)生回壓?jiǎn)栴}。 實(shí)驗(yàn)使用wrk作為施壓方,wrk是一個(gè)基于事件機(jī)制的高性能HTTP壓力測(cè)試工具,能用很少的線程產(chǎn)生極高的訪問壓力。實(shí)驗(yàn)統(tǒng)計(jì)性能測(cè)試指標(biāo)如表2所示。 表2 性能測(cè)試指標(biāo) 4.3.1并發(fā)性能分析 為了評(píng)價(jià)本文提出的并發(fā)模型對(duì)于提高服務(wù)網(wǎng)格并發(fā)性能的有效性,本文設(shè)計(jì)相關(guān)實(shí)驗(yàn)與目前主流的服務(wù)網(wǎng)格系統(tǒng)Linkerd和Envoy進(jìn)行比較,在相同實(shí)驗(yàn)條件下,用wrk測(cè)試三者的性能表現(xiàn)。 實(shí)驗(yàn)結(jié)果顯示本文原型系統(tǒng)和Envoy(C++實(shí)現(xiàn))有非常相似的表現(xiàn),兩者性能都明顯優(yōu)于Linkerd。詳細(xì)結(jié)果如表3-表5所示,從延時(shí)分布上分析,并發(fā)連接從128并發(fā)連接上升到512并發(fā)連接的過程中,BWM和Envoy的延遲分布比Linkerd更穩(wěn)定。具體來(lái)說,Linkerd的平均延遲從58.42 ms至117.66 ms,增加101.40%,在相比之下,BWM和Envoy的平均延遲從約52 ms增加到約72 ms,增加38.46%。Linkerd的延遲變化很大,以512并發(fā)連接實(shí)驗(yàn)為例,Linkerd的50%的請(qǐng)求在80.44 ms內(nèi),99%的所有請(qǐng)求在522.44 ms內(nèi),相比之下,BWM和Envoy的變化僅從約67 ms(50%)到大約145 ms(99%)。 表3 128并發(fā)連接下的測(cè)試結(jié)果 表4 256并發(fā)連接下的測(cè)試結(jié)果 表5 512并發(fā)連接下的測(cè)試結(jié)果 可以看出BWM和Envoy的性能表現(xiàn)明顯優(yōu)于Linkerd。最初,128并發(fā)連接下,三者性能差異很小,其中BWM的表現(xiàn)最為優(yōu)秀,BWM和Envoy的差距不大,但是兩者都明顯優(yōu)于Linkerd,Linkerd僅比其他兩個(gè)低約12%;256并發(fā)連接下,Linkerd、BWM和Envoy的QPS分別為3 005.75、4 559.11、4 583.77,512并發(fā)連接下,Linkerd、BWM和Envoy的QPS分別為5 085.25、7 015.28、7 146.75,差距隨著并發(fā)的增加而增加。需要注意的是,雖然BWM的性能和Envoy是非常相似的,但是最大響應(yīng)時(shí)間(Max.RT)BWM均比Envoy小,考慮C++語(yǔ)言比Java存在的一定性能優(yōu)勢(shì),因此BWM的性能表現(xiàn)十分優(yōu)秀。 4.3.2交互性能分析 為了評(píng)價(jià)本文設(shè)計(jì)的通信協(xié)議(BWMP)的有效性,本文在相同實(shí)驗(yàn)條件下,分別測(cè)試使用HTTP協(xié)議通信和自定義協(xié)議通信下的性能表現(xiàn)。 實(shí)驗(yàn)結(jié)果如表6所示,可見使用BWMP協(xié)議傳輸數(shù)據(jù)總量平均減少約9.26%,QPS平均增加約5.41%,說明BWMP協(xié)議對(duì)性能有一定的影響和提高。 表6 通信性能測(cè)試結(jié)果 4.3.3程序語(yǔ)言層面分析 眾所周知,編程語(yǔ)言的特性直接影響所實(shí)現(xiàn)系統(tǒng)的整體性能。本文原型系統(tǒng)和Linkerd都是基于Java實(shí)現(xiàn),而Envoy則基于C++實(shí)現(xiàn)。C++是基于靜態(tài)類型編譯的編程語(yǔ)言,在本質(zhì)上相比于Java更加高效。因此,從程序語(yǔ)言層面來(lái)看,Envoy的性能應(yīng)該顯著優(yōu)于BWM和Linkerd,但實(shí)驗(yàn)結(jié)果是BWM和Envoy的性能相近,顯著優(yōu)于采用同樣編程語(yǔ)言的Linkerd。因此考慮到編程語(yǔ)言本身對(duì)系統(tǒng)性能的影響,本文提出的服務(wù)網(wǎng)格性能優(yōu)化方法起到了很好的優(yōu)化效果。 服務(wù)網(wǎng)格是面向服務(wù)計(jì)算的新型基礎(chǔ)設(shè)施,為服務(wù)的靈活交互和全面的服務(wù)治理與服務(wù)監(jiān)控提供支撐。服務(wù)網(wǎng)格的性能優(yōu)化是提升系統(tǒng)并發(fā)處理能力的有效途徑。本文從計(jì)算模型和通信協(xié)議兩個(gè)方面提出了服務(wù)網(wǎng)格性能優(yōu)化的關(guān)鍵技術(shù),設(shè)計(jì)了基于Reactor的高性能并發(fā)模型和輕量化的通信協(xié)議與高效的編解碼算法。通過實(shí)驗(yàn)與當(dāng)前主流的服務(wù)網(wǎng)格系統(tǒng)Linkerd和Envoy進(jìn)行了性能對(duì)比,分別從并發(fā)性能和通信性能方面進(jìn)行分析比較,實(shí)驗(yàn)結(jié)果表明本文方法在響應(yīng)時(shí)間和網(wǎng)絡(luò)傳輸數(shù)據(jù)量方面均起到了性能優(yōu)化作用。 目前本文的實(shí)驗(yàn)只是基于簡(jiǎn)單的模擬場(chǎng)景對(duì)提出方法的有效性進(jìn)行了分析對(duì)比,后續(xù)工作將基于更多的真實(shí)應(yīng)用更加深入和詳細(xì)地進(jìn)行實(shí)驗(yàn)和分析。此外,未來(lái)工作將從負(fù)載均衡和調(diào)度算法方面繼續(xù)深入研究服務(wù)網(wǎng)格的性能優(yōu)化技術(shù),并將相關(guān)成果應(yīng)用于主流的開源服務(wù)網(wǎng)格系統(tǒng),以進(jìn)一步分析評(píng)估方法的有效性。3 系統(tǒng)設(shè)計(jì)
4 實(shí) 驗(yàn)
4.1 實(shí)驗(yàn)設(shè)計(jì)
4.2 評(píng)價(jià)指標(biāo)
4.3 實(shí)驗(yàn)結(jié)果分析
5 結(jié) 語(yǔ)