1. 程式人生 > >HSF的原理分析

HSF的原理分析

二進制 反序列化 心跳檢測 線路 text rac handle sdn 初始化

http://blog.csdn.net/qq_16681169/article/details/72512819

一.HSF的基本概念

HSF全稱為High-Speed Service Framework,旨在為淘系的應用提供一個分布式的服務框架,HSF從分布式應用層面以及統一的發布/調用方式層面為大家提供支持,從而可以很容易的開發分布式的應用以及提供或使用公用功能模塊,而不用考慮分布式領域中的各種細節技術,例如遠程通訊、性能損耗、調用的透明化、同步/異步調用方式的實現等等問題。

二.知識準備

通過以上的說明,大致了解了一下RPC與HSF的總體架構,但是總體架構離具體實現還想差很多,有些知識準備還是很有必要的。

1.對象的序列化

對象的序列化過程在RPC過程中是很重要的一個環節,序列化對於遠程調用的響應速度、吞吐量、網絡帶寬消耗等同樣也起著至關重要的作用。
在HSF1.0時只支持兩種序列化方式:java 和 hessian,在HSF2.0之後就支持了五種序列化方式:java、hessian、hessian2、json、kyro。
但是目前版本中常用的序列化方式還是java 和 hessian兩種。如果想細致的了解也可以多做了解。

2.動態代理

對於消費方來說,所存在的只有一個接口,雖然底層的實現原理我們知道,但是為了在使用時的高度透明,在JAVA語言層面上的表現形式則是通過動態代理的方式實現的,很多的邏輯都在InvocationHandler 中處理的。關於如何實現動態代理,還動態代理的一些使用的細節也可以稍作了解。

3.網絡通信NIO

如果在網絡傳輸過程中,采取普通的BIO,會有很多的問題存在,例如如果調用端有多個請求過來,那麽就得需要多個線程去處理,每個線程都使用獨立的連接,在遠端的提供者端有對應的多個線程來執行相應的服務。這種方式會使得調用者和提供者之間建立大量的連接,而且是阻塞的方式,連接並不能得到充分的利用(摘自《大型網站系統與JAVA中間件》)。采用NIO則就可以避免這樣的損耗,但是HSF在使用時並不是采用直接的NIO編程,而是通過第三方的框架Netty。

二.HSF 實現原理

1.提供服務的大致流程如下:
? server啟動時候向configserver註冊
? client啟動時候向configserver請求list
? client緩存list,發現不可用的server,從緩存中remove
? configserver通過心跳包維護可用server的list
? list有更新的時候,configserver通過帶version的報文通知client更新

技術分享

從以上幾個問題出發,看下HSF的實現方式。

2.HSF的整體實現方式:

技術分享

從圖中可以看出,HSF的實現方式可以理解為是C/S的架構,但是和傳統的C/S架構相比還是有很大的不同,HSF沒有真正的服務器,每個應用都可以成為服務的調用方和提供方。具體工作方式如下:

ConfigServer:遠程調用對端的地址就是由ConfigServer 來推送的,這樣用戶只需要配置自己的服務端或者消費端,不需要對自己的地址進行管理。

Diamond:持久化的配置中心,用於配置服務調用的規則。

服務:服務是調用方和提供方交流的依憑,一般是一個接口,表示一個業務行為以及相關的數據含義。通過使用HSFApiProviderBean能夠暴露一個服務,將機器的地址註冊到configserver,並且能夠通過12200端口進行服務提供,通過HSFApiConsumerBean能夠包裝出一個客戶端,它是服務接口的一個代理,並且它從configserver上訂閱了服務的地址列表,能夠在這個列表上完成隨機調用,做到負載均衡與HA((High Available,高可用性群集)。

網絡通信:HSF的底層網絡通信是使用netty框架實現的,是基於epoll的NIO的網絡通訊框架,HSF在此使用的是長連接,通過合理的服務部署及負債均衡,基本不存在I/O方面的限制。

三.HSF設計架構

技術分享
關於HSF的架構基本可以理解為C/S結構設計方式。(雖然HSF沒有自己的服務器)
Server端除了configServer外還有一個diamond用來保存一些持久化的配置信息,這裏不進行過多的介紹。

Client是HSF的重點,下面是各模塊的功能介紹:
Proxy:這一層主要負責接口的代理。基本上所有的RPC框架都會用到代理模式,相信大家不陌生。需要註意的是HSF的代理層還進行了軟負載和單元化的處理。
Remoting:這一層是HSF的應用層協議,定義了報文格式,各個字段的含義等信息,內容比較多,之後單獨寫一篇文章來介紹。
Processer:這一層主要是處理HSF自身的業務邏輯,包括埋點、限流、鑒權等。
Netty:上面三層會將一次服務調用或者服務返回包裝成一個報文,然後通過這層傳輸。

HSF調用流程

技術分享
上圖是HSF整個的調用過程,從左向右看:
第一條線路相當於consumer進行服務調用的過程,首先經過proxy層,將請求經過代理類包裝出去;然後是Remoting層進行協議的包裝,最後io層發送出去。
第二條線路相當於provider將結果返回後解析的過程,與上一流程剛好相反。
右邊的provider兩條調用流程相信大家都能按照上面的過程理解,就不一一講解了。

四.HSF處理請求流程

1.HSF提供端初始化

技術分享

2.HSF消費端初始化

技術分享

3.消費方請求到提供方,響應一次調用

技術分享

4.實現細節

心跳檢測:

1、客戶端主動關閉連接:客戶端第一次與服務端建立鏈接後,就會周期性(27s)發送心跳包的callback調用,如果連續三次收不到服務端的心跳包回應,客戶端主動關閉鏈接

2、服務端主動關閉連接:當連接59s沒有調用(對方網絡不可用,或者full gc太久),相當於兩次(2*27s)收不到心跳包的時間

從上圖可以看出RPC要解決以下幾個問題:

如何解決網絡通信問題,主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調用的所有交換的數據都在這個連接裏傳輸。連接可以是按需連接,調用結束後就斷掉,也可以是長連接,多個遠程過程調用共享同一個連接。

如何解決尋址問題,客戶端如何找到制定的服務端,也就是保證準確有效的完成一次服務調用的前提。

參數的傳遞及服務端在收到客戶端請求後如何實現其具體功能並返回,由於網絡傳輸協議是二進制的,內存中的參數值必須要解決序列化,反序列化,以及對半包,粘包的處理。

五.HSF的優點:

1.服務的自動註冊、發現

通過註冊中心,實現服務的註冊/註銷與服務的發現。當服務啟動後,會調用publish來將服務發布到中心,而服務的消費者,通過調用訂閱接口傳入的監聽器來更新服務提供者列表。HSF提供了三種註冊中心實現,分別是ConfigServer,Zookeper,和配置文件模式。

技術分享

這裏僅對Zookeper進行分析,ZookeeperMetadataAddressService 實現了上述接口,在初始化中實例化了一個ZookeeperRegistry來進行管理,其使用了一個封裝了zookeperclient的實例-ZkclientZookeeperClient,在註冊服務的時候根據url參數中的Constants.DYNAMIC_KEY來確定創建Persistent節點還是Ephemeral節點,Ephemeral節點生命周期與本機連接綁定,這樣就可以實現本機離線後的服務自動註銷的功能。

2) 服務提供者與消費者之間長連接。

HSF采用長連接方式進行通信,相比短連接,長連接更具性能優勢,避免連接重復創建與銷毀帶來的緩沖區申請與釋放。HSF抽象了連接AbstractClient(Client),並采用了netty框架作為底層實現。netty是一個性能非常優秀的通信框架,基於反應器模式,內部采用了管線模式來解耦不同層次的邏輯之間的耦合問題。HSF為了強化TCP連接的可用性,增加HeartBeat功能,使用了一個Netty提供的 HashedWheelTimer 的定時任務調度器來執行心跳包的發送(補充:此HashedWheelTimer原理采用輪片式的桶結構,避免每次操作對全部任務的叠代操作,只對將要到期的桶進行操作,此原理也可用於緩存系統設計,在需要進行垃圾回收的情況下只需要按照桶為單位進行內存回收)。

3) 非侵入性

HSF最大優點是非侵入性,它使用了JAVA的Proxy機制來實現這一特點,在通過xml配置文件配置Consumer的時候,實際上是調用了 HSFApiConsumerBean ,在它的初始化方法中,讀取了配置的實現接口,並在ProcessComponent中用一個封裝了Proxy註冊功能,並實現了InvocationHandler接口的類HSFServiceProxy去管理。使用者在自己的代碼中無需做任何特殊處理,就像使用本地方法一樣去調用其方法。

技術分享

4) 版本管理

這一特性可以很靈活的幫助上線運營的服務在升級過程中避免服務不可用的情況。

5) 服務治理

可以通過網頁可視化查看、管理、測試服務的可用。

6) 擴展靈活

可以接入自動服務降級功能(熔斷) - 根據配置或服務的執行結果,在調用級控制服務是否調用執行,避免服務整體癱瘓,提升服務的可用性。

HSF的原理分析