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