前言HSF是一個分布式的遠程服務調(diào)用框架,其實我更喜歡把分布式幾個字去掉,因為HSF本身并不是一個單獨的服務(指一個進程),他是附屬在你的應用里的一個組件,一個RPC組件(遠程過程調(diào)用——Remote Procedure Call,是一種通過網(wǎng)絡(luò)從遠程計算機程序上請求服務,而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。在OSI網(wǎng)絡(luò)通信模型中,RPC跨越了傳輸層和應用層。RPC使得開發(fā)分布式應用更加容易),當然HSF完全的內(nèi)容肯定不止這些。 說了那么久HSF全稱是什么呢?High-Speed Service Framework RPC我們先來看一張圖: ![]() hsf-up.png
很多同學看了這張圖可能會覺得這跟http的過程有什么區(qū)別? 有這么一個場景(本來想舉一個便具體業(yè)務的例子,想想還是已技術(shù)實現(xiàn)相關(guān)的比較好),監(jiān)控平臺:監(jiān)控所有主機的狀態(tài),這時候每臺主機上有一個agent,每個幾秒向監(jiān)控平臺上傳一次數(shù)據(jù)(主機內(nèi)存使用率、硬盤狀況、CPU、load、進程信息等等)。 可能在開發(fā)的時候最簡單的方式就是監(jiān)控平臺有一個http接口,agent每隔幾秒請求一次,能夠滿足需求,但是如果主機數(shù)快速增長了很多、監(jiān)控項越來越多、請求體越來越大,你會發(fā)現(xiàn)http的傳輸效率下降了,每一次調(diào)用的耗時增加了。 這時我們會去研究http協(xié)議,想去優(yōu)化這個過程,發(fā)現(xiàn)http的過程是:建立連接、發(fā)送請求信息、發(fā)送響應信息、關(guān)閉連接,看到這個過程首先想優(yōu)化的就是能不能不要每次都去建立連接關(guān)閉連接,因為數(shù)據(jù)上報是個持續(xù)的過程;緊接著去研究http頭,發(fā)現(xiàn)很多協(xié)議用不到,繁雜,白白增加了消息體;后來又覺得http的協(xié)議解析還原過程很復雜,可以自己開發(fā)一個提升性能...... RPC來了,他能滿足這些需求,但是前提是需要開發(fā),需要前期成本,所以想項目設(shè)計時就要去衡量,不過沒事,我們有HSF啊。 我們將上圖稍微改造一下: ![]() hsf-http-rpc.png
現(xiàn)在從圖中可以看著,client和server之間有一條長連接,并且我們有自己的協(xié)議體:RpcRequest和RpcResponse。 RPC就講到這里,畢竟重點是HSF,想要更多的了解RPC,可以上wiki或者網(wǎng)上查詢。 HSF架構(gòu)其實在我們的應用中,一般情況下你的應用不僅僅是client,也是server,因為你不僅需要去調(diào)用其他應用提供的服務,也提供服務給其他應用,所以這樣一來,整個hsf的服務調(diào)用鏈路也會很復雜。 從上面兩幅圖中我們很顯然的發(fā)現(xiàn)一個問題,就是服務提供者如何告知客戶端他提供的服務,所以需要有一個服務注冊與發(fā)現(xiàn)的地方,在HSF架構(gòu)中提供這個功能的是configserver,如下圖: ![]() hsf-configserver.png
從上圖可以看出server端啟動的時候會向configserver注冊自己提供的服務,client會向configserver訂閱需要的服務,configserver通過訂閱信息將相關(guān)服務提供者的地址以及其他關(guān)鍵信息推送給client。 上面已經(jīng)實現(xiàn)了基本的能力,但是如何動態(tài)配置負載(線程池大?。?、默認配置(configserver地址等)、還有一些特性功能(如路由規(guī)則),這時候就需要有一個持久化配置中心,如下圖: ![]() hsf-diamond.png
client和server啟動的時候會先去diamond獲取需要的配置信息,如最關(guān)鍵的服務注冊中心的類型和地址,除此之外之外還有服務治理的類型和地址等。 重點說一下路由規(guī)則,舉個例子:通過路由規(guī)則配置在服務調(diào)用的時候只調(diào)用同機房的server,這樣子服務調(diào)用的耗時肯定比跨機房的耗時短。除此之外hsf里還單獨寫了unitService進行服務單元發(fā)布來區(qū)分中心發(fā)布,這些番外的東西以后有時間再寫個番外篇,這里就不過多闡述了,畢竟這些有點偏場景偏業(yè)務的內(nèi)容以后可能就改成別的方式了。 ![]() hsf-ops.png
相信大家都用過hsf服務治理網(wǎng)站,通過這個網(wǎng)站可以看到有哪些服務、服務提供者的地址是多少、有多少提供者、具體的消費者是誰,hsf通過configserver、redis、diamond里的存儲信息獲取到這些信息。 redis功能:HSF使用Redis存儲元數(shù)據(jù),每一個HSF Consumer/Provider 都會在啟動后、每隔一段時間向redis上報元數(shù)據(jù),這些元數(shù)據(jù)采集起來又提供給HSFOPS做服務治理,包括應用名和服務的映射、服務的元數(shù)據(jù)等。 服務的注冊與發(fā)布![]() hsf-server.png
接下來我們把這個server解開,看看里面是怎么樣的。 <bean id='hsfTestService'
class='com.test.service.impl.HsfTestServiceImpl' />
<bean class='com.taobao.hsf.app.spring.util.HSFSpringProviderBean'
init-method='init'>
<property name='serviceName' value='hsfTestService' />
<property name='target' ref='hsfTestService' />
<property name='serviceInterface'>
<value>com.test.service.HsfTestService
</value>
</property>
<property name='serviceVersion'>
<value>${hsf.common.provider.version}</value>
</property>
</bean>
相信同學們對上面這段配置代碼很熟悉,那么服務到底是怎么注冊的呢,為什么這里配置了這個服務就可以被調(diào)用了呢? 從配置文件看到有個關(guān)鍵的bean——HSFSpringProviderBean,還有個關(guān)鍵的初始化方法init,其實init的過程就是服務發(fā)布的過程,我們來看看HSFSpringProviderBean中的部分代碼:
從代碼中很明顯的看到服務發(fā)布providerBean.publish(),先來看大致類圖,類圖中有些不是很關(guān)鍵的先省略了: ![]() hsf-server-uml.png
大致對類圖進行解釋一下,這也是服務發(fā)布的一個過程:
服務注冊發(fā)布大致就是這么一個過程。 HSF的Client![]() hsf-client.png
現(xiàn)在來看看client是如何去調(diào)用服務的。 <bean id='hsfTestService' class='com.taobao.hsf.app.spring.util.HSFSpringConsumerBean' init-method='init'>
<property name='interfaceName' value='com.test.service.hsfTestService'/>
<property name='version' value='1.0.0.daily'/>
</bean>
上面一段配置文件相信在項目中肯定也非常常見,那么他是怎么運作的呢?在spring注入的時候并沒有具體的實現(xiàn)類啊,只有一個接口?怎么實現(xiàn)調(diào)用的呢? 其實這是我一個好奇心的地方,我想去看個究竟,hsf到底是用何種方式去實現(xiàn)的。 我們先來思考一個問題,那就是沒有具體實現(xiàn)類,hsf是如何實現(xiàn)在spring中注冊服務的呢?答案就是動態(tài)代理,類似mybatis的方式,mybatis在寫dao層的時候只是寫了個接口,并沒有具體實現(xiàn),hsf跟這種方式很相像。 客戶端分兩部分來講解:服務的訂閱和被推送,服務的調(diào)用。 服務的訂閱和被推送先來看類圖: ![]() hsf-client-uml.png
一樣我們通過類圖來看服務的訂閱和接收過程:
到此為止,服務代理對象的生成,服務的訂閱都完成了,接下來看看服務的調(diào)用。 服務的調(diào)用其實通過上面兩個部分整個框架已經(jīng)定好了,服務信息已經(jīng)注冊發(fā)布,客戶端也獲取到了服務的調(diào)用地址,接下去就是調(diào)用就行,調(diào)用呢就是真正的rpc請求了,hsf的rpc是通過netty實現(xiàn)的。 直接上類圖: ![]() hsf-call.png
之前說了動態(tài)代理,那么在方法執(zhí)行時就行進入代理類執(zhí)行,執(zhí)行HSFServiceProxy的invoke方法,invoke方法會調(diào)用trueInvoke方法:
簡單說下服務端的流程:
![]() total.png
寫在最后我在這里講得更多的是主鏈路,里面有很多具體的細節(jié)比如路由、鷹眼追蹤、日志、負載等等沒有展開講,其實每個點拿出來都可以寫一篇文章,可能對于hsf的開發(fā)同學來說,每一個點都會有一個很好玩的故事,那么關(guān)于HSF就先講到這里。 |
|
來自: liang1234_ > 《dubbo》