金志國,李煒
(1 北京郵電大學網絡與交換技術國家重點實驗室,北京 100876;2 東信北郵信息技術有限公司,北京 100191)
基于Netty的HTTP客戶端的設計與實現(xiàn)
金志國1,2,李煒1,2
(1 北京郵電大學網絡與交換技術國家重點實驗室,北京 100876;2 東信北郵信息技術有限公司,北京 100191)
能力開放平臺是一個提供電信能力開放的移動互聯(lián)網開放平臺,向開發(fā)者提供豐富的業(yè)務能力,包括:短信、彩信、地圖、定位等。能力開放平臺接入系統(tǒng)需要異步處理客戶端的HTTP請求,而平臺內部各個系統(tǒng)間的消息傳遞也需要使用大量的異步HTTP請求。Netty是一款異步的事件驅動的網絡應用開源框架,用于快速開發(fā)可維護的高性能、高擴展性協(xié)議服務器和客戶端。本文簡述了通過對開源框架Netty的源碼封裝,提供方便易用可以發(fā)送異步HTTP請求的客戶端的設計思路和具體實現(xiàn)。
Netty框架;NIO 技術;異步;HTTP客戶端
云計算是服務的交付和使用模式,指通過網絡以按需、易擴展的方式獲得所需服務。在云計算技術發(fā)展日新月異的今天,業(yè)界開始更多的轉向云平臺。能力開放平臺是基于PaaS(Platform as a Service,平臺即服務)提供電信能力開放的移動互聯(lián)網開放云平臺,向開發(fā)者提供豐富的業(yè)務能力,包括:短信、彩信、地圖、定位等。在能力開放平臺的接入系統(tǒng)部分,需要處理海量的請求。在用戶體驗不斷提高的要求下,能力開放平臺業(yè)務處理日益復雜造成交互延遲,傳統(tǒng)的Web請求同步模式下業(yè)務處理的阻塞造成的延遲已經滿足不了高并發(fā)需求[1]。
在接入系統(tǒng)內部以及接入系統(tǒng)與其他系統(tǒng)之間,多采用HTTP進行數(shù)據(jù)傳輸。由接入系統(tǒng)接受客戶傳來的請求,進行異步處理,但系統(tǒng)內部的信息傳輸仍然采用同步模式時,則會造成阻塞,異步的Web服務器也失去了意義。所以,在云平臺項目開發(fā)過程中急需要一個可以支持大并發(fā)高效穩(wěn)定的異步HTTP客戶端[2]。
目前,異步HTTP客戶端只有Apache Http Components項目的HttpAsyncClient 4.0-beta4,但仍然是對外測試版。其他的異步框架,如Mina、Netty和Grizzly,均是以Java NIO(Non-Blocking I,非阻塞IO)為基礎。本文通過調研,選定采用Netty作為底層源碼實現(xiàn)異步HTTP客戶端。
Netty[3]是一款異步的事件驅動的網絡應用框架和工具,用于快速開發(fā)可維護的高性能、高擴展性協(xié)議服務器和客戶端。Netty是一個基于Java NIO[4]客戶端/服務器框架,支持快速、簡單地開發(fā)網絡應用,如協(xié)議服務器和客戶端。
圖1 HTTP客戶端總體模塊圖
Netty具有以下優(yōu)勢:
(1)對阻塞和非阻塞的socket提高統(tǒng)一的API;
(2)高度可定制化的線程模型;
(3)基于攔截鏈模式的事件模型有很高的靈活性和擴展性;
(4)對多種協(xié)議的支持,包括HTTP、TCP、UDP、SMTP、FTP以及二進制文本協(xié)議,完全支持SSL/TLS,適用于快速開發(fā)各種高級組件。
2.1 總體設計
本文是以Netty框架[3]為底層,將Netty提供的對HTTP協(xié)議的支持,編解碼等功能封裝成異步HTTP客戶端,提供簡單易懂的API使用,可以很容易的發(fā)送HTTP請求,并異步處理HTTP響應。
基于Netty的HTTP客戶端總體模塊設計[5]見圖1所示,設計思路如下:
(1) 提供一個整體的配置類,作為API的入口;
(2) 針對不同的配置類,生成不同的異步客戶端啟動類;
(3) 由異步客戶端負責發(fā)送異步和同步的HTTP請求。
2.2 網絡模型
Netty基于Java NIO設計并實現(xiàn),因此它實現(xiàn)異步的方式與Java NIO類似,采用的網絡模式是reactor模式。
每個Worker其實表示的是Selector和Thread一種組合,如圖2所示。每次創(chuàng)建一個連接,都會選擇一個Worker,并且注冊到Worker里的Selector,Worker會進行l(wèi)oop,不斷地關注通道事件,也就是會說每個Worker(Selector)下會注冊多個Channel,并且不斷地去Select關注的Channel。Selector在發(fā)現(xiàn)感興趣的事件后,直接調用Channel的Pipeline進行處理。
圖2 worker線程模型[3]
2.3 事件驅動模式
消息處理模型采用的是基于事件的Pipeline模式。Pipeline實際上可以理解為對Channel的filter chain,可以通過在Pipeline中定義多個handler來處理各種事件。
Channel表示一個與socket關聯(lián)的通道。ChannelPipeline是管道,一個Channel擁有一個ChannelPipeline,負責維護兩個處理鏈,即upstream鏈和downstream鏈。處理鏈由多個處理句柄ChannelHandler構成,每個ChannelHandler處理完以后會傳遞給鏈中的下一個處理句柄繼續(xù)處理。ChannelHandler是處理句柄,用戶可以定義自己的處理句柄來處理每個請求,或發(fā)出請求前進行預處理,典型的處理句柄有編解碼器decoder和encoder。ChannelEvent事件是整個模型的處理對象,當產生或觸發(fā)一個事件時,該事件會沿著ChannelPipeline處理鏈依次被處理。ChannelFuture表示異步結果,這個是異步事件處理的關鍵,當一個事件被處理時,可以直接以ChannelFuture的形式直接返回,不用在當前操作中被阻塞??梢酝ㄟ^ChannelFuture得到最終的執(zhí)行結果,具體的做法是在ChannelFuture添加監(jiān)聽器listener,當操作最終被執(zhí)行完后,listener會被觸發(fā),我們可以在listener的回調函數(shù)中預定義我們的業(yè)務代碼。
ChannelPipeline維持兩個處理鏈:upstream、downstream。Upstream一般處理來自Channel的讀事件,而downstream一般處理向Channel的寫事件。需要注意的是,這兩個處理鏈是相互獨立的,在upstream鏈中傳遞到最后一個ChannelHandler處理后,不會再傳遞到downstream鏈中繼續(xù)處理。
在downstream鏈的末端會有個ChannelSink處理,用戶可以自定義這個ChannelSink的實現(xiàn),系統(tǒng)也有個默認的實現(xiàn),當downstream鏈中最后一個ChannelHandler處理完后會被傳遞給這個ChannelSink進行最后的處理。
2.4 詳細設計
2.4.1 配置類
圖3定義了總配置的接口,具體的配置實現(xiàn)類通過實現(xiàn)總配置的接口,實現(xiàn)自己的配置信息。
圖3 配置類圖
Netty的配置類部分內容見表1。
2.4.2 啟動類
通過將配置類NettyConfig作為參數(shù)傳入給異步客戶端類[5], 異步客戶端類會根據(jù)配置類的類型,返回不同的啟動類。如果傳入NettyConfig,則調用nettyProvider。對應調用Netty底層的bootstrap幫助類,封裝成異步客戶端啟動類返回給用戶。用戶則可以通過該啟動類發(fā)送同步或者異步HTTP請求。
由Netty的網絡模型(2.2章節(jié))可知,Netty底層采用線程池處理消息的發(fā)送和接受,boss線程和worker分別各用一個線程池,即需要兩個線程池。如果每次發(fā)送一條HTTP請求,都新啟動一個Netty客戶端類,對應生成新啟動兩個線程池,開銷較大,Netty的性能也完全沒有利用起來。由此,設計時采用單例模式,只生成一個AsyncHttpClient異步客戶端實例,所有的請求都是通過這個客戶端實例進行發(fā)送的。
表1 配置項
2.4.3 編解碼類
因為Netty消息處理采用事件驅動模式,編解碼的工作在Pipeline中進行。Netty已經提供好了多種HTTP[6]的編解碼類,如HttpResponseDecoder(對HTTP響應進行解碼工作),HttpRequestEncoder(對HTTP請求進行編碼工作)。
在Pipeline中除去編解碼類,剩下最主要的就是需要我們自己定義的響應處理邏輯類HttpResponse Handler,該類需要繼承SimpleChannelUpstream Handler類。經過Decoder解碼后的HTTP響應消息會傳遞到處理邏輯類,方便我們響應進行操作。
這里采用了一種巧妙的設計思路,讓 Netty的啟動類NettyHttpClient繼承SimpleChannelUpstream Handler類,使得響應的處理邏輯也可以通過Netty啟動類配置。統(tǒng)一了API的使用。
獲取返回消息,定義了兩種方式:
(1) 通過默認的handler處理邏輯,獲取結果時,通過阻塞的方式,等待默認handler得到結果后,將結果返回。
(2) 通過自定義的回調函數(shù),實現(xiàn)客戶端代碼的異步。當有消息時,會自動通知客戶端。通過實現(xiàn)回調函數(shù)接口,可以對響應進行多種操作。
2.4.4 設計模式
本文在設計異步客戶端時,參考了很多開源框架[5]的設計原理,采用了工廠模式、Builder模式和單例模式等方法實現(xiàn)[7]。
(1)工廠模式
使用工廠模式構建配置類和啟動類,如圖4所示,不同的框架實現(xiàn)不同的配置類。異步客戶端類根據(jù)配置類的類型,產生不同的異步客戶端啟動類,進行HTTP請求的發(fā)送。為以后擴展其他的框架實現(xiàn)方式提供了接口支持。
(2)Builder模式
因為配置類有很多參數(shù)需要配置,如果對每一種可能的情況都設置一個構造器,工作量將是非常巨大的,而且可讀性很差。采用Builder模式,不直接生成需要的對象,而是讓客戶端利用所有必要的參數(shù)調用構造器(類似于靜態(tài)工廠的方式),得到一個Builder對象。然后通過對Builder對象上調用類似于setter的方法,來設置每一個相關的可選參數(shù)。Builder是配置類的靜態(tài)成員類,通過調用Build方法來生成不可變的對象。
(3)單例模式
通過單例模式可以保證系統(tǒng)中一個類只有一個異步客戶端實例可以被外界訪問,從而方便對實例個數(shù)的控制并節(jié)約系統(tǒng)資源,避免了每次發(fā)送請求構建線程池和銷毀線程池的開銷,高并發(fā)量下,功能得到了保障,性能得到了提高。
2.5 分析測試和結果
在完成了基于Netty的HTTP客戶端開發(fā)工作了,對幾種HTTP客戶端的性能進行了簡單的比較。比較了3種HTTP客戶端。2種異步客戶端,分別為本文實現(xiàn)的客戶端, HttpAsyncClient。1種同步客戶端,HttpClient。
圖4 工廠模式
通過跑10 000個HTTP的GET請求,得出結果:使用異步的NettyHttpClient共用時間5 972 ms,使用異步的HttpAsyncClient共用時間9 021 ms,使用同步的HttpClient共用時間29 310 ms。從測試結果分析,發(fā)現(xiàn)異步客戶端比同步客戶端效率要高很多,而基于Netty實現(xiàn)的異步HTTP客戶端效率要比apache要高。
本文所述的基于Netty的異步HTTP客戶端已經完成。配置類提供了25個配置項,包括Netty啟動的配置項,以及HTTP請求的配置項。同時提供同步和異步HTTP請求,包括GET, POST, DELETE, PUT。還提供發(fā)送單向的HTTPS請求的功能。目前,本客戶端已經應用在實驗室多個項目中。尤其在消息解析引擎中,作為必不可少的一部分。
本文設計并實現(xiàn)的異步HTTP客戶端,其設計思路借鑒了很多開源框架的設計原則,始終本著使用簡單,低耦合和高內聚的軟件設計思路進行的實現(xiàn)。采用的都是通用接口設計,方便以后擴展。
雖然本客戶端已經滿足了項目中的基本需求,但是還有部分功能沒有實現(xiàn),下一步需要進一步研究的問題是完善本客戶端的功能和配置項。同時,考慮到不同的異步框架性能和實現(xiàn)原理的差異性,需要將其他的異步框架也融入進去,使得用戶可以選擇性使用不同的底層實現(xiàn),來滿足自己不同的功能或者性能需求。
[1] 鄭建軍. Java在高并發(fā)網絡編程中的應用[J]. 電腦編程技巧與維護,2013(18):50-52.
[2] Goetz B. Java并發(fā)編程實戰(zhàn)[M]. 北京:機械工業(yè)出版社華章公司,2012.
[3] JBoss. Netty project[CP/OL]. [2012-4-1]. http://netty.io/
[4] Hitchens R. Java NIO[M]. USA: O'Reilly Media, 2002.
[5] Jfarcand. The Async Http Client[CP/OL]. [2012-3-16]. http:// sonatype.github.io/async-http-client/
[6] Gourley D, Totty B. HTTP權威指南[M]. 北京:人民郵電出版社,2012.
[7] 梅特斯克. Java設計模式[M]. 北京:人民郵電出版社,2007.
Design and implementation of HTTP client based on Netty
JIN Zhi-guo1,2, LI Wei1,2
(1 State Key Laboratory of Networking and Switching Technology, Beijing University of Posts and Telecommunications, Beijing 100876, China; 2 EBUPT Information Technology Co., Ltd., Beijing 100191, China)
Open Mobile Platform is an Open Platform providing ability of telecommunication. It provides developers with rich business abilities, including: SMS, MMS, maps, positioning, etc. The access system of Open Mobile Platform requires asynchronous processing HTTP requests for the client, and various systems of the platform also need to use a large number of asynchronous HTTP requests to send message. Netty is an asynchronous event-driven network applications open source framework, which is used for rapid development of maintainable high performance, high scalability protocol servers and clients. This paper briefy describes the design idea and concrete implementation of using open source framework Netty for providing a convenient and easy http client which can send an asynchronous HTTP request.
Netty framework; NIO technology; asynchrony; HTTP client
TN915
A
1008-5599(2014)01-0084-05
2013-12-05
國家973計劃項目(No. 2013CB329102);國家自然科學基金資助項目(No. 61372120,61271019, 61101119, 61121001, 61072057, 60902051);長江學者和創(chuàng)新團隊發(fā)展計劃資助(No. IRT1049);北京市支持中央高校共建項目——青年英才計劃。