dubbo詳細學習筆記
第一章 基本概念
1. 什麼是dubbo
dubbo是一款高性能的RPC架構,可以和Spring架構無縫內建。dubbo提供了三大核心能力,面向接口的遠端方法調用,智能容錯和負載均衡以及服務自動注冊和發現
具體介紹參考dubbo官網:dubbo官網
2. 什麼是RPC
RPC即遠端過程調用,比如兩台伺服器A和B,A伺服器上部署一個應用,B伺服器部署一個應用,A伺服器上的應用調用B伺服器上的應用提供的方法,由于兩個應用不在一個記憶體空間,不能直接調用,是以需要通過網絡來表達調用的語義和傳達調用的資料。RPC架構比較多,像RMI,Hessian,gRPC ,dubbo等,核心子產品就是網絡通訊和序列化。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPBFmeohVZqhmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLkN2YzAzYyYjZkJzYxMDOidjYlRDZjlDZ2I2YxIzMxU2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
RPC調用過程圖如下:
3. RMI
(1)概念
RMI是java原生支援的遠端調用,采用JRMP作為通信協定,可以認為是java版本的分布式遠端調用方案。
(2)核心概念
(3)RMI實作步驟
① 建立遠端接口,并且繼承java.rmi.Remote接口
② 實作遠端接口,并且繼承UnicastRemoteObject
③ 建立伺服器程式,createRegistry()方法注冊遠端對象
④ 建立用戶端程式,擷取注冊資訊,調用接口方法
具體實作如下:
4. Hessian
(1)Hessian使用C/S方式,基于HTTP協定傳輸,使用Hessian二進制序列化
(2)具體實作
server端,為war包,需要配置web.xml
① 導入依賴
② 建立接口
③ web.xnl
用戶端
① 添加Hessian依賴
② 建立server端相同的接口,用戶端需要用到服務端的接口
③ 建立測試類進行測試
第二章 dubbo高可用
1. 叢集容錯
(1)服務路由
服務路由包含一條路由規則,決定了服務消費者的調用目标,規定了服務消費者可調用哪些服務提供者
① [服務消費者比對條件]=>[服務提供者比對條件]
例如:host=10.20.152.10=>host=10.20.153.11
表示IP為10.20.152.10的服務消費者隻可調用IP為10.20.153.11機器上的服務
② 常用路由配置
白名單
host!=10.20.152.10,10.20.152.11=>
表示除了這兩個其他都可以調用
黑名單
host=10.20.152.10,10.20.152.11
這兩個ip不能進行消費,服務禁用
讀寫分離
method=find,list,get,is=>host=172.22.3.94,172.22.3.9,172.22.3.96
method!=find,list,get,is=>host=172.22.3.97,172.22.3.98
前背景分離
application=front=>host=172.22.3.92,172.22.3.93
application!=front=>host=172.22.3.92,172.22.3.93
(2)叢集容錯
① Failover Cluster失敗自動切換,當出現失敗,重試其他伺服器,通常用于讀操作,可通過retries=“2”設定重試次數
<dubbo :server retries=“2”/>或<dubbo :reference retries=“2”/>
② Failfast Cluster快速失敗,隻發起一次調用,失敗立即報錯,通常用于非幂等性的寫操作,比如新增記錄
③ Failsafe Cluster 失敗安全,出現異常時,直接忽略,通常用于寫入日志等操作
④ Failback Cluster失敗自動恢複,背景記錄失敗請求,定時重發,通常用于消息通知操作
⑤ Forking Cluster 并行調用多個伺服器,隻要一個成功即傳回,通常用于實時性要求較高的讀操作,可通過forks="2"來設定最大并行數
⑥ Broadcast Cluster廣播調用所有提供者,逐個調用,任意一台報錯則報錯,通知用于通知所有提供者更新緩存或日志等本地資源資訊
(3)負載均衡
① Random LoadBalance:按照權重設定随機機率,無狀态
② RoundRobin LoadBalance:輪詢,有狀态
③ LeastActive LoadBalance:最少活躍數随機,方法次元的統計服務調用數
④ ConsistentHash LoadBalance:一緻性Hash
2. 服務治理
(1)服務降級
服務提供方的編寫:
① dubbo配置-application.xml
② 提供方接口實作暴露的接口
③ web.xml 設定監聽
服務消費者的編寫
① 配置檔案-application.xml
② 編寫web.xml
③ controller層代碼
mock配置方式
mock的配置支援兩種,一種是boolean值,預設的為false,配置為true,則預設使用mock類名,即類名+Mock字尾;另外一種是配置“return null”,可以簡單的忽略掉異常
① mock配置在消費方,當消費方正常運作,擷取傳回值時為null
② mock=“return null”會對service中的所有方法做統一處理。都傳回null值,如果我們要做其他處理則配置mock=“true”,同時實作mock接口,接口名+Mock字尾,如果調用失敗則會嗲用Mock實作,mock實作需要保證無參的構造方法
在暴露的接口編寫Mock實作類
3. 高可用整合Hystrix
(1) 添加依賴
(2)在主程式啟動類上添加注解@EnableHystrix開啟Hystrix功能
(3)在提供方增加@HystrixCommand注解,這樣調用會經過Hystrix代理
(4)在消費方增加@HystrixCommand注解并指定出錯是的回調方法,當出錯時,會調用fallbackMethod裡的方法
4. dubbo線程IO模型
(1)BIO:每個用戶端連接配接過來後,服務端會啟動一個線程去處理該用戶端的請求,阻塞I/O的通信
在傳統的IO模型中,每個連接配接建立成功之後都需要一個線程來維護
(2)NIO:非阻塞IO,新來一個連接配接不在建立一個新的線程,而是把這條連接配接直接綁定到某個固定的線程,然後這條連接配接所有的讀寫都由這個線程負責
對比兩種IO
說明:
① IO模型中,一個連接配接對應建立一個線程,對應一個死循環,死循環的目的就是不斷監測這條連接配接上是否有資料可讀,但是在大多數情況下,很多個while循環都白白浪費,沒有資料
② NIO模型中可以把這麼多的while死循環變成一個死循環,這個死循環由一個線程控制,這就是NIO模型中的選擇器的作用,一條連接配接來了,不是建立一個while死循環去監聽是否有資料可讀了,而是直接把這條連接配接注冊到選擇器上,通過檢查這個選擇器,就可以批量監測出有資料可讀的連接配接,進而讀取資料
5. dubbo原理
說明:
① config配置層:對外配置接口,以ServiceConfig,ReferenceConfig為中心,可以直接初始化配置類也可以通過spring解析配置生成配置類
② proxy服務代理層:服務接口透明代理,生成服務的用戶端stub和伺服器端skeleton,以ServiceProxy為中心,擴充接口為ProxyFactory
③ registry注冊中心:封裝服務位址的注冊于發現,以服務URL為中心,擴充接口為RegistryFactory,Registry,RegistryService
6. dubbo SPI機制
(1)具體實作
① 建立一個接口和實作類
② dubbo SPI所需的配置檔案放置在META-INF/dubbo路徑下,其檔案的包路徑要和service的包路徑一緻,檔案内容如下:根據key來進行通路的
③ 進行測試
dubbo SPI的相關邏輯被封裝在ExtensionLoader類中,通過ExtensionLoader,我們可以加載指定的實作類,這裡需要注意的是需要在接口上标注@SPI注解,根據key來對應通路具體的實作類
(2)源碼分析
① 通過getExtensionLoader方法擷取一個ExtensionLoader執行個體,該方法先從緩存中擷取與擴充類對應的ExtensionLoader,若緩存未命中,則建立一個新的執行個體
② getExtension方法中,檢查緩存,未命中則調用createExtension方法建立擴充對象
③ createExtension方法包含如下步驟:
通過getExtensionClasses擷取所有的擴充類
通過反射建立擴充對象
向擴充對象中注入依賴
将擴充對象包裹在相應的Wrapper對象中
injectExtension方法依賴注入實作原理:dubbo首先會通過反射擷取到執行個體的所有方法,然後在周遊方法清單,檢測方法名是否具有setter方法特征,若有,則通過ObjectFactory擷取依賴對象,最後通過反射調用setter方法将依賴設定到目标對象中
7. dubbo服務暴露源碼分析
(1)spring容器啟動,會加載BeanDefinitionParser類來解析配置檔案,dubbo配置檔案的加載依賴實作類DubboBeanDefinitionParser,DubboBeanDefinitionParser解析器會将配置檔案中不同的标簽解析成不同的xxxConfig,<dubbo:service/>,<dubbo:reference/>分别解析成serviceBean和referenceBean
(2)serviceBean實作了InitializingBean和ApplicationListener接口,在afterPropertiesSet方法中主要将配置檔案中屬性依次配置到對應的bean中,在spring上下文重新整理事件後會回調onApplicationEvent方法
(3)調用父類ServiceConfig對象的export方法,檢查延遲是否導出,執行doExportUrls
(4)doExportURLs方法首先通過loadRegistries加載注冊中心連結,後在周遊ProtocolConfig集合導出每個服務,并在導出服務的過程中,将服務注冊到注冊中心
(5)doExportUrlsForProtocol方法主要将版本,時間戳,方法名以及各種配置對象的字段資訊放入到map中,map中的内容将作為URL的查詢字元串,建構好map後,緊接着是擷取上下文路徑,主機名和端口号資訊,最後将map和主機名等資料傳給URL構造方法建立RUL對象
(6)導出服務
scope=none則不做處理,scope!=remote導出本地服務,scope!=local則導出遠端服務,不管哪一種導出服務,都需要建立Invoke對象,它是ProxyFactory代理工廠建立的對象,invoke封裝了調用實體,根據scope參數,決定導出服務到本地還是遠端
8. dubbo服務引入
(1)引入時機
① 在spring容器調用ReferenceBean的afterPropertiesSet方法時引用服務,餓漢式的
② 在ReferenceBean對應的服務被注入到其他類中的引用,懶漢式的
預設情況下dubbo使用懶漢式服務,可以通過配置dubbo:reference的init屬性進行重新開機