java開發(fā)分布式服務框架Dubbo原理機制詳解
前言
在介紹Dubbo之前先了解一下基本概念:
Dubbo是一個RPC框架,RPC,即Remote Procedure Call(遠程過程調用),相對的就是本地過程調用,在分布式架構之前的單體應用架構和垂直應用架構運用的都是本地過程調用。它允許程序調用另外一個地址空間(通常是網絡共享的另外一臺機器)的過程或函數(shù),并且不用程序員顯式編碼這個遠程調用的細節(jié)。
而分布式架構應用與應用之間的遠程調用就需要RPC框架來做,目的就是為了讓遠程調用像本地調用一樣簡單。

Dubbo框架有以下部件
Consumer
即調用遠程服務的服務消費方,消費者需要面向接口編程,知道了哪些接口可以調用了,具體實現(xiàn)需要框架提供一個代理類來為接口提供具體實現(xiàn),讓消費者只管調用什么接口,而具體實現(xiàn)的獲取由代理類來處理。
消費者還需要提供調用方法名以及方法的參數(shù)值。
但是代理類此時還不知道需要調用哪個服務器上的遠程方法,此時需要一個注冊中心,通過注冊中心獲取可以調用的遠程服務列表。
遠程服務器一般都是集群部署,那么調用哪個服務器則需要通過負載均衡來選擇一個最合適的服務器來調用。
同時還需要有集群容錯機制,因為各種原因,可能遠程調用會失敗,此時需要容錯機制來重試調用,保證遠程調用的穩(wěn)定性。
同時與服務提供方約定好通信協(xié)議和序列化格式,方便通信以及數(shù)據(jù)傳輸。
Provider
即暴露服務的服務提供方,服務提供方內部實現(xiàn)具體的接口,然后將接口暴露出去,再將服務注冊到注冊中心,服務消費方調用服務,提供者接收到調用請求后,通過約定好的通信協(xié)議來處理該請求,然后做反序列化,完成后,將請求放入線程池中處理,某個線程接收到這個請求然后找到對應的接口實現(xiàn)進行調用,然后將調用結果原路返回。
Registry
即服務注冊與發(fā)現(xiàn)的注冊中心,注冊中心負責服務地址的注冊與查找,相當于服務目錄,服務提供者和消費者只會再啟動時與注冊中心交互,注冊中心不轉發(fā)請求,壓力小。

注冊中心還可以集中化處理配置以及動態(tài)地將變更通知訂閱方。
但是為什么需要注冊中心呢?沒有注冊中心不可以嗎?
在沒有注冊中心,各服務之間的調用關系是這樣的:

當服務越來越多時,服務URL配置管理變得非常困難,硬件負載均衡器的單點壓力也越來越大,而有了注冊中心之后,就可以實現(xiàn)服務的統(tǒng)一管理,并且實現(xiàn)軟負載均衡,降低硬件成本,以下為注冊中心示意圖:

Monitor
即統(tǒng)計服務調用次數(shù)和調用時間的監(jiān)控中心,面對眾多服務,精細化的監(jiān)控和方便的運維是不可或缺的,對后期維護相當重要。
Container
即服務運行的容器。
架構

圖中的各個節(jié)點充當?shù)慕巧呀浗榻B過了,以下是各節(jié)點之間調用關系:
Container服務容器負責啟動,加載以及運行
Provider服務提供者Provider服務提供者啟動時,需要將自身暴露出去讓遠程服務器可以發(fā)現(xiàn),同時向Registry注冊中心注冊自己提供的服務
Consumer服務消費者啟動時,向Registry注冊中心訂閱所需要的服務
Registry注冊中心返回服務提供者列表給消費者,同時如果發(fā)生變更,注冊中心將基于長連接推送實時數(shù)據(jù)給消費者
服務消費者需要調用遠程服務時,會從提供者的地址列表中,基于負載均衡算法選出一臺提供者服務器進行調用,如果調用失敗,會基于集群容錯策略進行調用重試
服務消費者與提供者會在內存中統(tǒng)計調用次數(shù)和調用時間,然后通過定時任務將數(shù)據(jù)發(fā)送給Monitor監(jiān)控中心
高可用性
- 監(jiān)控中心宕機后不會對服務造成影響,只是丟失部分統(tǒng)計數(shù)據(jù)
- 注冊中心集群后,任意一臺宕機后,將自動切換到其他注冊中心
- 當所有注冊中心均宕機后,服務提供者和消費者之間仍然能通過本地記錄了彼此信息的緩存進行通訊,但是如果一方產生變更,另外一方無法感知
- 服務提供者無狀態(tài),任意一臺服務器宕機后不影響使用,會有其他服務提供者提供服務
- 當所有服務提供者宕機后,服務消費者無法正常使用,將進行無限次重連等待服務提供者重新連線恢復
框架設計

大的分層為Business(業(yè)務邏輯層)、RPC層和Remoting層。
再細分下來,Dubbo一共有十層架構,作用分別如下:
Service,業(yè)務層,即日常開發(fā)中的業(yè)務邏輯層
Config,配置層,對外配置接口,以ServiceConfig 和ReferenceConfig為中心,可以直接初始化配置類,也可以通過Spring解析配置生成配置類
Proxy,服務代理層,服務接口透明代理,生成服務的客戶端Stub和客戶端Skeleton,負責遠程調用和返回結果
Registry,注冊中心層,封裝服務地址的注冊與發(fā)現(xiàn),以服務URL為中心,拓展接口為RegistryFactory,Registry,RegistryService
Cluster路由和集群容錯層,封裝了多個提供者的路由、負載均衡以及集群容錯,并橋接注冊中心,負責通過負載均衡選取調用具體的節(jié)點,處理特殊調用請求和負責遠程調用失敗的容錯措施
Monitor,監(jiān)控層,負責監(jiān)控統(tǒng)計RPC調用次數(shù)和調用時間
Portocol,遠程調用層,主要封裝RPC遠程調用方法
Exchange,信息交換層,用于封裝請求響應模型
Transport,網絡傳輸層,抽象化網絡傳輸統(tǒng)一接口,有Mina和Netty可供使用
Serialize,序列化層,將數(shù)據(jù)序列化成二進制流進行傳輸,也可以反序列化接收數(shù)據(jù)
服務暴露過程
首先Provider啟動,Protocal通過Proxy代理將需要暴露的接口封裝成Invoker,是一個可執(zhí)行體,然后通過Exporter包裝并發(fā)送到注冊中心完成注冊,至此服務就暴露完成。

服務消費過程

注:上圖中藍色部分為服務消費者,綠色部分為服務提供者。
服務消費者啟動時會向注冊中心訂閱并拉取所需服務提供者的信息,并保存到本地緩存,由此即使所有注冊中心宕機后,服務提供者和服務消費者也可以通過本地緩存進行通訊,只是一方出現(xiàn)了信息變更,另一方無法感知,但并不影響服務的進行。
之后整個服務消費流程從圖中的Proxy開始,由代理類完成處理,以此到達透明無感知。
ProxyFactory生成一個Proxy代理類,Proxy持有一個Invoker可執(zhí)行對象,調用invoke之后需要通過Cluster從Directory中獲取所有可調用的遠程服務Invoker列表,如果配置了某些路由規(guī)則,還需要再過濾一遍Invoker列表。
剩下的Invoker再通過LoadBalance做負載均衡選取一個,還需要再通過Filter進行一些數(shù)據(jù)統(tǒng)計,之后將這些數(shù)據(jù)保存下來,定時發(fā)送給Monitor。
接下來用Client做數(shù)據(jù)傳輸,一般用Netty進行傳輸。
傳輸需要通過Codec接口進行協(xié)議構造,然后再通過Serialization進行序列化,最后將序列化后的二進制流發(fā)送至給對應的服務提供者。
服務提供者接收到二進制流后也會進行Codec協(xié)議處理,然后進行反序列化(此處的處理與傳輸之前的處理是呈對稱的)后將請求放入線程池中處理,某個線程會根據(jù)請求找到對應的Exporter,然后再通過Filter進行層層過濾得到Invoker,最終調用對應的實現(xiàn)類然后將結果原路返回。
如有錯誤或不足歡迎評論指正。
以上就是java開發(fā)分布式服務框架Dubbo原理機制詳解的詳細內容,更多關于Dubbo分布式服務框架原理機制的資料請關注腳本之家其它相關文章!
相關文章
java文件下載設置中文名稱的實例(response.addHeader)
下面小編就為大家分享一篇java文件下載設置中文名稱的實例(response.addHeader),具有很好的參考價值,希望對大家有所幫助2017-12-12
解決IDEA2021版compiler.automake.allow.when.app.running不存在的問題
很多文章介紹IntelliJ IDEA開啟熱部署功能都會寫到在IntelliJ IDEA中的注冊表中開啟compiler.automake.allow.when.app.running選項,此選項在IntelliJ IDEA 2021.2之后的版本遷移到高級設置中,下面看下設置方法2021-09-09
淺談s:select 標簽中l(wèi)ist存放map對象的使用
下面小編就為大家?guī)硪黄獪\談s:select 標簽中l(wèi)ist存放map對象的使用。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11

