Dubbo實現原理淺析


參考:

https://blog.csdn.net/paul_wei2008/article/details/19355681

https://blog.csdn.net/ygl19920119/article/details/88342523

https://blog.csdn.net/l_bestcoder/article/details/79368530

https://blog.csdn.net/chao_19/article/details/51764150

 

 

 

 

Dubbo基本原理機制

分布式服務框架:
–高性能和透明化的RPC遠程服務調用方案
–SOA服務治理方案
-Apache MINA 框架基於Reactor模型通信框架,基於tcp長連接
Dubbo缺省協議采用單一長連接和NIO異步通訊,
適合於小數據量大並發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況
分析源代碼,基本原理如下:
  1. client一個線程調用遠程接口,生成一個唯一的ID(比如一段隨機字符串,UUID等),Dubbo是使用AtomicLong從0開始累計數字的
  2. 將打包的方法調用信息(如調用的接口名稱,方法名稱,參數值列表等),和處理結果的回調對象callback,全部封裝在一起,組成一個對象object
  3. 向專門存放調用信息的全局ConcurrentHashMap里面put(ID, object)
  4. 將ID和打包的方法調用信息封裝成一對象connRequest,使用IoSession.write(connRequest)異步發送出去
  5. 當前線程再使用callback的get()方法試圖獲取遠程返回的結果,在get()內部,則使用synchronized獲取回調對象callback的鎖, 再先檢測是否已經獲取到結果,如果沒有,然后調用callback的wait()方法,釋放callback上的鎖,讓當前線程處於等待狀態。
  6. 服務端接收到請求並處理后,將結果(此結果中包含了前面的ID,即回傳)發送給客戶端,客戶端socket連接上專門監聽消息的線程收到消息,分析結果,取到ID,再從前面的ConcurrentHashMap里面get(ID),從而找到callback,將方法調用結果設置到callback對象里。
  7. 監聽線程接着使用synchronized獲取回調對象callback的鎖(因為前面調用過wait(),那個線程已釋放callback的鎖了),再notifyAll(),喚醒前面處於等待狀態的線程繼續執行(callback的get()方法繼續執行就能拿到調用結果了),至此,整個過程結束。
  • 當前線程怎么讓它“暫停”,等結果回來后,再向后執行?
     答:先生成一個對象obj,在一個全局map里put(ID,obj)存放起來,再用synchronized獲取obj鎖,再調用obj.wait()讓當前線程處於等待狀態,然后另一消息監聽線程等到服 務端結果來了后,再map.get(ID)找到obj,再用synchronized獲取obj鎖,再調用obj.notifyAll()喚醒前面處於等待狀態的線程。
  • 正如前面所說,Socket通信是一個全雙工的方式,如果有多個線程同時進行遠程方法調用,這時建立在client server之間的socket連接上會有很多雙方發送的消息傳遞,前后順序也可能是亂七八糟的,server處理完結果后,將結果消息發送給client,client收到很多消息,怎么知道哪個消息結果是原先哪個線程調用的?
     答:使用一個ID,讓其唯一,然后傳遞給服務端,再服務端又回傳回來,這樣就知道結果是原先哪個線程的了。
 
 
 
 
 
 
 
 
 

dubbo的工作原理

轉載地址:https://blog.csdn.net/A_BlackMoon/article/details/85609328;https://blog.csdn.net/Cs_orange/article/details/82313866

dubbo的工作原理

1、面試題

說一下的dubbo的工作原理?注冊中心掛了可以繼續通信嗎?說說一次rpc請求的流程?

2、面試官心里分析

MQ、ES、Redis、Dubbo,上來先問你一些思考的問題,原理(kafka高可用架構原理、es分布式架構原理、redis線程模型原理、Dubbo工作原理),生產環境里可能會碰到的一些問題(每種技術引入之后生產環境都可能會碰到一些問題),系統設計(設計MQ,設計搜索引擎,設計一個緩存,設計rpc框架),

當然比如說,hard面試官,死扣,結合項目死扣細節,百度(深入底層,基礎性),阿里(結合項目死扣細節,扣很深的技術底層),小米(數據結構和算法)。

那既然開始聊分布式系統了,自然重點先聊聊dubbo了,畢竟dubbo是目前事實上大部分公司的分布式系統的rpc框架標准,基於dubbo也可以構建一整套的微服務架構。但是需要自己大量開發。

當然去年開始spring cloud非常火,現在大量的公司開始轉向spring cloud了,spring cloud人家畢竟是微服務架構的全家桶式的這么一個東西。但是因為很多公司還在用dubbo,所以dubbo肯定會是目前面試的重點,何況人家dubbo現在重啟開源社區維護了,未來應該也還是有一定市場和地位的。

既然聊dubbo,那肯定是先從dubbo原理開始聊了,你先說說dubbo支撐rpc分布式調用的架構是啥,然后說說一次rpc請求dubbo是怎么給你完成的,對吧。

3、面試題剖析

(1)dubbo工作原理

第一層:service層,接口層,給服務提供者和消費者來實現的
第二層:config層,配置層,主要是對dubbo進行各種配置的
第三層:proxy層,服務代理層,透明生成客戶端的stub和服務單的skeleton
第四層:registry層,服務注冊層,負責服務的注冊與發現
第五層:cluster層,集群層,封裝多個服務提供者的路由以及負載均衡,將多個實例組合成一個服務
第六層:monitor層,監控層,對rpc接口的調用次數和調用時間進行監控
第七層:protocol層,遠程調用層,封裝rpc調用
第八層:exchange層,信息交換層,封裝請求響應模式,同步轉異步
第九層:transport層,網絡傳輸層,抽象mina和netty為統一接口
第十層:serialize層,數據序列化層

工作流程:

1)第一步,provider向注冊中心去注冊
2)第二步,consumer從注冊中心訂閱服務,注冊中心會通知consumer注冊好的服務
3)第三步,consumer調用provider
4)第四步,consumer和provider都異步的通知監控中心

在這里插入圖片描述

dubbo的工作原理.png

(2)注冊中心掛了可以繼續通信嗎?

可以,因為剛開始初始化的時候,消費者會將提供者的地址等信息拉取到本地緩存,所以注冊中心掛了可以繼續通信。

(3)Dubbo的執行流程:

項目一啟動,加載配置文件的時候,就會初始化,服務的提供方ServiceProvider就會向注冊中心注冊自己提供的服務,當消費者在啟動時,就會向注冊中心訂閱自己所需要的服務,如果服務提供方有數據變更等,注冊中心將基於長連接的形式推送變更數據給消費者。
默認使用Dubbo協議:
連接個數:單連接
連接方式:長連接
傳輸協議:TCP
傳輸方式:NIO異步傳輸
序列化:Hessian二進制序列化
適用范圍:傳入傳出參數數據包較小(建議小於100K),消費者比提供者個數多,單一消費者無法壓滿提供者,盡量不要使用dubbo協議傳輸大文件或超大字符串
使用場景:常規遠程服務方法調用
從上面的適用范圍總結,dubbo適合小數據量大並發的服務調用,以及消費者機器遠大於生產者機器數的情況,不適合傳輸大數據量的服務比如文件、視頻等,除非請求量很低。

(4)Dubbo的安全性如何得到保障:
a.在有注冊中心的情況下,可以通過dubbbo admin中的路由規則,來指定固定ip的消費方來訪問
b.在直連的情況下,通過在服務的提供方中設置密碼(令牌)token,消費方需要在消費時也輸入這 個密碼,才能夠正確使用。
Dubbo添加服務ip白名單,防止不法調用

(5)Duubo中如何保證分布式事務?
一般情況下,我們盡量將需要事務的方法放在一個service中,從而避開分步式事務。
Dubbo底層是基於socket: Socket通信是一個全雙工的方式,如果有多個線程同時進行遠程方法調用,這時建立在client server之間的socket連接上會有很多雙方發送的消息傳遞,前后順序也可能是亂七八糟的,server處理完結果后,將結果消息發送給client,client收到很多消息,怎么知道哪個消息結果是原先哪個線程調用的?
答:使用一個ID,讓其唯一,然后傳遞給服務端,再服務端又回傳回來,這樣就知道結果是原先哪個線程的了。

(6)Dubbo的心跳機制:
目的:
維持provider和consumer之間的長連接
實現:
dubbo心跳時間heartbeat默認是1s,超過heartbeat時間沒有收到消息,就發送心跳消 息(provider,consumer一樣),如果連着3次(heartbeatTimeout為heartbeat*3)沒有收到心跳響應,provider會關閉channel,而consumer會進行重連;不論是provider還是consumer的心跳檢測都是通過啟動定時任務的方式實現;

Dubbo的zookeeper做注冊中心,如果注冊中心全部掛掉,發布者和訂閱者還能通信嗎?
可以通信的,啟動dubbo時,消費者會從zk拉取注冊的生產者的地址接口等數據,緩存在本地。每次調用時,按照本地存儲的地址進行調用;
注冊中心對等集群,任意一台宕機后,將會切換到另一台;注冊中心全部宕機后,服務的提供者和消費者仍能通過本地緩存通訊。服務提供者無狀態,任一台 宕機后,不影響使用;服務提供者全部宕機,服務消費者會無法使用,並無限次重連等待服務者恢復;
掛掉是不要緊的,但前提是你沒有增加新的服務,如果你要調用新的服務,則是不能辦到的。

 
 
 
 
 
 
 
 

Dubbo實現原理淺析

 
 
 
 
 
 
 
 

Dubbo解析及原理淺析

一、Duboo基本概念解釋

Dubbo是一種分布式服務框架。 Webservice也是一種服務框架,但是webservice並不是分布式的服務框架,他需要結合F5實現負載均衡。因此,dubbo除了可以提供服務之外,還可以實現軟負載均衡。它還提供了兩個功能Monitor 監控中心和調用中心。這兩個是可選的,需要單獨配置。

Dubbo的計數架構圖如下:

這里寫圖片描述

我們解釋以下這個架構圖:

Consumer服務消費者,Provider服務提供者。Container服務容器。消費當然是invoke提供者了,invoke這條實線按照圖上的說明當然同步的意思了,多說一句,在實際調用過程中,Provider的位置對於Consumer來說是透明的,上一次調用服務的位置(IP地址)和下一次調用服務的位置,是不確定的。這個地方就是實現了軟負載。

服務提供者先啟動start,然后注冊register服務。

消費訂閱subscribe服務,如果沒有訂閱到自己想獲得的服務,它會不斷的嘗試訂閱。新的服務注冊到注冊中心以后,注冊中心會將這些服務通過notify到消費者。

Monitor這是一個監控,圖中虛線表明Consumer 和Provider通過異步的方式發送消息至Monitor,Consumer和Provider會將信息存放在本地磁盤,平均1min會發送一次信息。Monitor在整個架構中是可選的(圖中的虛線並不是可選的意思),Monitor功能需要單獨配置,不配置或者配置以后,Monitor掛掉並不會影響服務的調用。

二、dubbo原理

本篇博客的內容總體上比較抽象,如果一個想馬上使用dubbo的同學來說,讀這篇博客效果不太好,本篇博客沒有寫怎么使用、配置dubbo,接下來,我再令寫一篇dubbo入門包含demo的博客。

I、初始化過程細節:
上圖中的第一步start,就是將服務裝載容器中,然后准備注冊服務。和Spring中啟動過程類似,spring啟動時,將bean裝載進容器中的時候,首先要解析bean。所以dubbo也是先讀配置文件解析服務。
解析服務:
1)、基於dubbo.jar內的Meta-inf/spring.handlers配置,spring在遇到dubbo名稱空間時,會回調DubboNamespaceHandler類。
2)、所有的dubbo標簽,都統一用DubboBeanDefinitionParser進行解析,基於一對一屬性映射,將XML標簽解析為Bean對象。
源碼截圖:
在ServiceConfig.export 或者ReferenceConfig.get 初始化時,將Bean對象轉會為url格式,將所以Bean屬性轉成url的參數。
然后將URL傳給Protocol擴展點,基於擴展點的Adaptive機制,根據URL的協議頭,進行不同協議的服務暴露和引用。
暴露服務:

a、 只暴露服務端口

在沒有使用注冊中心的情況,這種情況一般適用在開發環境下,服務的調用這和提供在同一個IP上,只需要打開服務的端口即可。
即,當配置 or
ServiceConfig解析出的URL的格式為:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0
基於擴展點的Adaptiver機制,通過URL的“dubbo://”協議頭識別,直接調用DubboProtocol的export()方法,打開服務端口。

b、向注冊中心暴露服務:

和上一種的區別:需要將服務的IP和端口一同暴露給注冊中心。
ServiceConfig解析出的url格式為:
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode(“dubbo://service-host/com.xxx.TxxService?version=1.0.0”)

基於擴展點的Adaptive機制,通過URL的“registry://”協議頭識別,調用RegistryProtocol的export方法,將export參數中的提供者URL先注冊到注冊中心,再重新傳給Protocol擴展點進行暴露:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

引用服務:

a、直接引用服務:

在沒有注冊中心的,直連提供者情況下,
ReferenceConfig解析出的URL格式為:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

基於擴展點的Adaptive機制,通過url的“dubbo://”協議頭識別,直接調用DubboProtocol的refer方法,返回提供者引用。

b、從注冊中心發現引用服務:

此時,ReferenceConfig解析出的URL的格式為:
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode(“consumer://consumer-host/com.foo.FooService?version=1.0.0”)

基於擴展點的Apaptive機制,通過URL的“registry://”協議頭識別,就會調用RegistryProtocol的refer方法,基於refer參數總的條件,查詢提供者URL,如:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

基於擴展點的Adaptive機制,通過提供者URL的“dubbo://”協議頭識別,就會調用DubboProtocol的refer()方法,得到提供者引用。
然后RegistryProtocol將多個提供者引用,通過Cluster擴展點,偽裝成單個提供這引用返回。

三、遠程調用細節:

服務提供者暴露一個服務的詳細過程:

這里寫圖片描述

上圖是服務提供者暴露服務的主過程:
首先ServiceConfig類拿到對外提供服務的實際類ref,然后將ProxyFactory類的getInvoker方法使用ref生成一個AbstractProxyInvoker實例,到這一步就完成具體服務到invoker的轉化。接下來就是Invoker轉換到Exporter的過程。
Dubbo處理服務暴露的關鍵就在Invoker轉換到Exporter的過程,下面我們以Dubbo和rmi這兩種典型協議的實現來進行說明:
Dubbo的實現:
Dubbo協議的Invoker轉為Exporter發生在DubboProtocol類的export方法,它主要是打開socket偵聽服務,並接收客戶端發來的各種請求,通訊細節由dubbo自己實現。
Rmi的實現:
RMI協議的Invoker轉為Exporter發生在RmiProtocol類的export方法,他通過Spring或Dubbo或JDK來實現服務,通訊細節由JDK底層來實現。

服務消費者消費一個服務的詳細過程

這里寫圖片描述

上圖是服務消費的主過程:
首先ReferenceConfig類的init方法調用Protocol的refer方法生成Invoker實例。接下來把Invoker轉為客戶端需要的接口

 
 
 
 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM