微服务面试必问的Dubbo,这么详细还怕自己找不到工作?
Dubbo 起源于阿里巴巴,對于我們做電商開發的人來說,基本是首選的技術,那么為何一個區區 soa 服務治理框架,會受到這么多人的青睞呢?
今天就跟著小羽一起看看這個微服務框架之一的 Dubbo 的詳細解讀吧。
前言
互聯網的不斷發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對。
服務化的進一步發展,服務越來越多,服務之間的調用和依賴關系也越來越復雜,誕生了面向服務的架構體系(SOA),
也因此衍生出了一系列相應的技術,如對服務提供、服務調用、連接處理、通信協議、序列化方式、服務發現、服務路由、日志輸出等行為進行封裝的服務框架。
就這樣分布式系統的服務治理框架就出現了,Dubbo也就這樣產生了。
概念
Dubbo 是一款高性能、輕量級的開源 RPC 框架、提供服務自動注冊、自動發現等高效治理方案,可以和 Spring 框架無縫集成。
簡單的說,dubbo就是個分布式服務框架,在有分布式需要的時候可以使用 dubbo 的框架,使用 dubbo 的好處:
1、透明化的遠程方法調用
2、軟負載均衡及容錯機制
3、服務自動注冊與發現
4、提供了完善的服務接口管理與監控功能
架構圖
?
?
RPC
簡介
RPC 全稱為 remote procedure call,即遠程過程調用。比如兩臺服務器 A 和 B,A 服務器上部署一個應用,B 服務器上部署一個應用,A 服務器上的應用想調用 B 服務器上的應用提供的方法,由于兩個應用不在一個內存空間,不能直接調用,所以需要通過網絡來表達調用的語義和傳達調用的數據。
RPC 并不是一個具體的技術,而是指整個網絡遠程調用過程。
RPC 是一個泛化的概念,嚴格來說一切遠程過程調用手段都屬于 RP C范疇。各種開發語言都有自己的 RPC 框架。Java 中的 RPC 框架比較多,廣泛使用的有 RMI、Hessian、Dubbo 等。
原理
服務消費方(client)調用以本地調用方式調用服務。客戶端存根(client stub)接收到調用后負責將方法、參數等編碼成能在網絡中傳輸的消息體。然后,客戶端存根找到服務地址后,將消息發送給服務端。
服務提供方(server)收到序列化后的消息,就按照解碼該消息。然后,根據解碼結果調用本地服務,執行完畢后,將結果打包發送給消費方。
服務消費方收到執行結果后,也是進行解碼后得到結果。
原理
?
?
使用場景
RPC 分布式服務,拆分應用進行服務化,提高開發效率,調優性能,節省競爭資源
配置管理,解決服務的地址信息劇增,配置困難的問題
服務依賴,解決服務間依賴關系錯蹤復雜的問題
服務擴容,解決隨著訪問量的不斷增大,動態擴展服務提供方的機器的問題
核心功能
Remoting:遠程通訊,提供對多種 NIO 框架抽象封裝,包括“同步轉異步”和“請求-響應”模式的信息交換方式。
Cluster:服務框架,提供基于接口方法的透明遠程過程調用,包括多協議支持,以及軟負載均衡,失敗容錯,地址路由,動態配置等集群支持。
Registry:服務注冊中心,服務自動發現: 基于注冊中心目錄服務,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。
核心組件
Provider:服務的提供方
Consumer:調用遠程服務的服務消費方
Registry:服務注冊和發現的注冊中心
Monitor:統計服務調用次數和調用時間的監控中心
Container:服務運行容器
組件
?
?
服務注冊與發現
流程如下:
1、Provider(提供者)綁定指定端口并啟動服務
2、供者連接注冊中心,并發本機 IP、端口、應用信息和提供服務信息發送至注冊中心存儲
3、Consumer(消費者),連接注冊中心 ,并發送應用信息、所求服務信息至注冊中心
4、注冊中心根據消費者所求服務信息匹配對應的提供者列表發送至Consumer 應用緩存。
5、Consumer 在發起遠程調用時基于緩存的消費者列表擇其一發起調用。
6、Provider 狀態變更會實時通知注冊中心、在由注冊中心實時推送至Consumer設計的原因:
Consumer 與 Provider 解偶,雙方都可以橫向增減節點數。注冊中心對本身可做對等集群,可動態增減節點,并且任意一臺宕掉后,將自動切換到另一臺
7、去中心化,雙方不直接依懶注冊中心,即使注冊中心全部宕機短時間內也不會影響服務的調用
8、服務提供者無狀態,任意一臺宕掉后,不影響使用
流程
?
?
服務治理
治理原因
Dubbo的服務治理主要原因:
1、過多的服務 URL 配置困難。
2、負載均衡分配節點壓力過大的情況下也需要部署集群。
3、服務依賴混亂,啟動順序不清晰。
4、過多服務導致性能指標分析難度較大,需要監控。
主要特性
透明遠程調用:就像調用本地方法一樣調用遠程方法;只需簡單配置,沒有任何 API 侵入
負載均衡機制:Client 端 LB,可在內網替代 F5 等硬件負載均衡器
容錯重試機制:服務 Mock 數據,重試次數、超時機制等
自動注冊發現:注冊中心基于接口名查詢服務提 供者的 IP 地址,并且能夠平滑添加或刪除服務提供者
性能日志監控:Monitor 統計服務的調用次調和調用時間的監控中心
服務治理中心:路由規則,動態配置,服務降級,訪問控制,權重調整,負載均衡,等手動配置
自動治理中心:無,比如:熔斷限流機制、自動權重調整等(因此可以搭配SpringCloud的熔斷機制等進行開發)
服務治理
?
?
架構設計
整體架構
先看下 Dubbo 的整體架構圖:
圖例說明:
整體架構
圖中左邊淡藍背景的為服務消費方使用的接口,右邊淡綠色背景的為服務提供方使用的接口,位于中軸線上的為雙方都用到的接口。
圖中從下至上分為十層,各層均為單向依賴,右邊的黑色箭頭代表層之間的依賴關系,每一層都可以剝離上層被復用,其中,Service 和 Config 層為 API,其它各層均為 SPI。
圖中綠色小塊的為擴展接口,藍色小塊為實現類,圖中只顯示用于關聯各層的實現類。
圖中藍色虛線為初始化過程,即啟動時組裝鏈,紅色實線為方法調用過程,即運行時調時鏈,紫色三角箭頭為繼承,可以把子類看作父類的同一個節點,線上的文字為調用的方法。
各層說明
config 配置層:對外配置接口,以 ServiceConfig, ReferenceConfig 為中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類
proxy 服務代理層:服務接口透明代理,生成服務的客戶端 Stub 和服務器端 Skeleton,以ServiceProxy 為中心,擴展接口為 ProxyFactory
registry 注冊中心層:封裝服務地址的注冊與發現,以服務 URL 為中心,擴展接口為RegistryFactory, Registry, RegistryService
cluster 路由層:封裝多個提供者的路由及負載均衡,并橋接注冊中心,以 Invoker 為中心,擴展接口為 Cluster, Directory, Router, LoadBalance
monitor 監控層:RPC 調用次數和調用時間監控,以 Statistics 為中心,擴展接口為MonitorFactory, Monitor, MonitorService
protocol 遠程調用層:封裝 RPC 調用,以 Invocation, Result 為中心,擴展接口為 Protocol, Invoker, Exporter
exchange 信息交換層:封裝請求響應模式,同步轉異步,以 Request, Response 為中心,擴展接口為 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
transport 網絡傳輸層:抽象 mina 和 netty 為統一接口,以 Message 為中心,擴展接口為 Channel, Transporter, Client, Server, Codec
serialize 數據序列化層:可復用的一些工具,擴展接口為 Serialization, ObjectInput, ObjectOutput, ThreadPool
主要模塊
dubbo-common 公共邏輯模塊,包括 Util 類和通用模型。
dubbo-remoting 遠程通訊模塊,相當于 Dubbo 協議的實現,如果 RPC 用 RMI 協議則不需要使用此包。
dubbo-rpc 遠程調用模塊,抽象各種協議,以及動態代理,只包含一對一的調用,不關心集群的管理。
dubbo-cluster 集群模塊,將多個服務提供方偽裝為一個提供方,包括:負載均衡、容錯、路由等,集群的地址列表可以是靜態配置的,也可以是由注冊中心下發。
dubbo-registry 注冊中心模塊,基于注冊中心下發地址的集群方式,以及對各種注冊中心的抽象。
dubbo-monitor 監控模塊,統計服務調用次數,調用時間的,調用鏈跟蹤的服務。
dubbo-config 配置模塊,是 Dubbo 對外的 API ,用戶通過 Config 使用 Dubbo ,隱藏 Dubbo 所有細節。
dubbo-container 容器模塊,是一個 Standalone 的容器,以簡單的 Main 加載 Spring 啟動,因為服務通常不需要 Tomcat/JBoss 等 Web 容器的特性,沒必要用 Web 容器去加載服務。
主要模塊
?
?
調用方式
異步調用
基于 NIO 的非阻塞實現并行調用,客戶端不需要啟動多線程即可完成并行調用多個遠程服務,相對多線程開銷較小
異步調用
本地調用
使用了Injvm協議,是一個偽協議,它不開啟端口,不發起遠程調用,只在JVM內直接關聯,但執行Dubbo的Filter鏈。
Define injvm protocol:
<dubbo:protocol?name="injvm"?/>Set default protocol:
<dubbo:provider?protocol="injvm"?/>Set service protocol:
<dubbo:service?protocol="injvm"?/>Use injvm first:(服務暴露與服務引用都需要聲明injvm=“true”)
<dubbo:consumer?injvm="true"?.../> <dubbo:provider?injvm="true"?.../> 或 <dubbo:reference?injvm="true"?.../>? <dubbo:service?injvm="true"?.../>?
?
容錯機制
調用流程
1、Cluster 將 Directory 中的多個 Invoker 偽裝成一個Invoker,對上層透明,偽裝過程包含了容錯邏輯
2、Router 負責從多個 Invoker 中按路由規則選出子集,比如讀寫分離,應用隔離等
3、LoadBalance 負責從多個 Invoker 中選出具體的一個用于本次調用,選的過程包含了負載均衡算法
調用流程
容錯策略
Dubbo 官網提出總共有六種容錯策略
1、Failover Cluster
失敗自動切換,當出現失敗,重試其它服務器。(默認)
2、Failfast Cluster
快速失敗,只發起一次調用,失敗立即報錯。通常用于非冪等性的寫操作,比如新增記錄。
3、Failsafe Cluster
失敗安全,出現異常時,直接忽略。通常用于寫入審計日志等操作。
4、Failback Cluster
失敗自動恢復,后臺記錄失敗請求,定時重發。通常用于消息通知操作。
5、Forking Cluster
并行調用多個服務器,只要一個成功即返回。通常用于實時性要求較高的讀操作,但需要浪費更多服務資源。
可通過 forks=”2”來設置最大并行數。
6、Broadcast Cluster
廣播調用所有提供者,逐個調用,任意一臺報錯則報錯。(2.1.0 開始支持) 通常用于通知所有提供者更新緩存或日志等本地資源信息。
總結:在實際應用中查詢語句容錯策略建議使用默認 Failover Cluster,而增刪改建議使用 Failfast Cluster 或者使用 Failover Cluster(retries=”0”)策略,防止出現數據重復添加等等其它問題!建議在設計接口時候把查詢接口方法單獨做一個接口提供查詢。
連接方式
Dubbo 的客戶端和服務端有三種連接方式,分別是:廣播、直連和使用Zookeeper注冊中心。
Dubbo 廣播
這種方式是dubbo官方入門程序所使用的連接方式,但是這種方式有很多問題,在企業開發中不使用廣播的方式。
服務端配置:
<!--配制dubbo--> <!--提供應用信息,用于計算依賴關系--> <dubbo:application?name="demo-service"/> <!--使用multicast廣播注冊暴露服務地址--> <dubbo:registry?address="multicast://192.168.9.4:88888"?/><!--使用dubbo協議在20880端口暴露服務--> <dubbo:protocol?name="dubbo"?port="20880"/><!--聲明暴露的服務接口--> <dubbo:service?interface="com.demo.manger.service.TestService"?ref="testServiceImpl"?/>客戶端配置:
<!--配合dubbo--> <!--提供應用信息,用于計算依賴關系--> <dubbo:application?name="demo-web"/><!--使用multicast廣播注冊中心暴露服務地址?--> <dubbo:registry?address="multicast://19.188.8.9:8888"/><!--聲明需要暴露的接口--> <dubbo:reference?interface="com.demo.manager.service.TestService"?id="testService"?timeout="1000000"?/>Dubbo 直連
這種方式在企業中一般在開發中環境中使用,但是生產環境很少使用,因為服務是直接調用,沒有使用注冊中心,很難對服務進行管理。Dubbo 直連,首先要取消廣播,然后客戶端直接到指定需要的服務的 url 獲取服務即可。
服務端配置:
<!--配制dubbo--> <!--提供應用信息,用于計算依賴關系--> <dubbo:application?name="demo-service"/> <!--使用multicast廣播注冊暴露服務地址--> <--?<dubbo:registry?address="multicast://192.168.9.4:88888"?/>?--> <dubbo:registry?adress="N/A"><!--使用dubbo協議在20880端口暴露服務--> <dubbo:protocol?name="dubbo"?port="20880"/><!--聲明暴露的服務接口--> <dubbo:service?interface="com.demo.manger.service.TestService"?ref="testServiceImpl"?/>客戶端配置:
<!--配合dubbo--> <!--提供應用信息,用于計算依賴關系--> <dubbo:application?name="demo-web"/><!--使用multicast廣播注冊中心暴露服務地址?--> <--?<dubbo:registry?address="multicast://19.188.8.9:8888"/>?--><!--聲明需要暴露的接口--> <dubbo:reference?interface="com.demo.manager.service.TestService"?id="testService"?timeout="1000000"?url="dubbo://127.0.0.1:20880"?/>zookeeper 注冊中心
Dubbo 注冊中心和廣播注冊中心配置類似,不過需要指定注冊中心類型和注冊中心地址,這個時候就不是把服務信息進行廣播了,而是告訴給注冊中心進行管理,這個時候我們就需要有一個注冊中心,官方推薦使用 zookeeper 作為注冊中心。
Zookeeper 注冊中心
注冊中心負責服務地址的注冊與查找,相當于目錄服務,服務提供者在啟動時與注冊中心交互,消費者不斷的發起請求獲取服務信息,注冊中心不轉發請求,壓力較小
服務端配置:
<!--配制dubbo--> <!--提供應用信息,用于計算依賴關系--> <dubbo:application?name="demo-service"/> <!--使用multicast廣播注冊暴露服務地址--> <!--?<dubbo:registry?address="multicast://192.168.9.4:88888"?/>?--> <!--<dubbo:registry?adress="N/A">?--> <dubbo:registry?protocol="zookeeper"?address="192.168.37,136:2181"> <!--使用dubbo協議在20880端口暴露服務--> <dubbo:protocol?name="dubbo"?port="20880"/><!--聲明暴露的服務接口--> <dubbo:service?interface="com.demo.manger.service.TestService"?ref="testServiceImpl"?/>客戶端配置:
<!--配合dubbo--> <!--提供應用信息,用于計算依賴關系--> <dubbo:application?name="demo-web"/><!--使用multicast廣播注冊中心暴露服務地址?--> <--?<dubbo:registry?address="multicast://19.188.8.9:8888"/>?--> <dubbo:registry?protocol="zookeeper"?address="192.168.37.1336:2181"/>????<!--聲明需要暴露的接口--> <dubbo:reference?interface="com.demo.manager.service.TestService"?id="testService"?timeout="1000000"?/>?
?
策略
負載均衡策略
1、Random LoadBalance,隨機(默認的負載均衡策略)
RandomLoadBalance 是加權隨機算法的具體實現,可以完全隨機,也可以按權重設置隨機概率。
2、RoundRobin LoadBalance,輪循
可以輪詢和加權輪詢。存在響應慢的提供者會累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。
3、LeastActive LoadBalance,最少活躍調用數
活躍調用數越小,表明該服務提供者效率越高,單位時間內可處理更多的請求。此時應優先將請求分配給該服務提供者。
4、ConsistentHash LoadBalance,一致性 Hash
一致性 Hash 算法,相同參數的請求一定分發到一個 provider 上去。provider 掛掉的時候,會基于虛擬節點均勻分配剩余的流量,抖動不會太大。
集群容錯策略
1、failover cluster(默認)
失敗自動切換,調用失敗時,自動重試其他機器。通常用于讀操作,但重試會帶來更長延遲。
2、Failfast Cluster
快速失敗,只發起一次調用,失敗立即報錯。通常用于非冪等性的寫操作,比如新增記錄。
3、Failsafe Cluster
失敗安全,出現異常時,直接忽略。通常用于寫入審計日志等操作。
4、Failback Cluster
失敗自動恢復,后臺記錄失敗請求,定時重發。通常用于消息通知操作。
5、Forking Cluster
并行調用多個服務器,只要一個成功即返回。通常用于實時性要求較高的讀操作,但需要浪費更多服務資源。
動態代理策略
默認使用 javassist 動態字節碼生成,創建代理類。也可以通過 spi 擴展機制配置自己的動態代理策略。
集群容錯方案
配置說明,方案配置方式,優先使用消費端配置
盡量在只在服務端進行配置
cluster類型均為小寫
默認為FailoverCluster失敗切換方案
集群容錯方案support
FailoverCluster(默認):失敗切換
場景:調用失敗后切換其他服務
配置:
代碼實現邏輯:
1. 根據負載均衡策略選出需要調用的服務實例,排除已調用的
2. 執行選出的實例,并將其保存到已調用列表中
3. 執行實例成功即返回
4. 執行實例不成功,為到最大重試次數則執行第一步,否則拋出RpcException異常
FailbackCluster:失敗重試
場景:調用失敗時記錄失敗請求,定時重發
配置:
代碼實現邏輯
1. 根據負載均衡策略選出需要調用的服務實例
2. 執行選出的實例
3. 執行實例成功即返回
4. 執行異常則創建延時5秒的定時任務,并加入時間輪定時器,第一次需要進行定時器初始化,分為32個時間片,每1秒滾動一次,最大掛起任務默認100個,超出最大任務數時拋出RejectedExecutionException異常。
5. 重試執行定時任務,次數超出最大執行次數停止,并輸出error日志,默認為3次。
FailfastCluster:快速失敗
場景:調用失敗立即報錯
配置:
代碼實現邏輯
1. 根據負載均衡策略選出需要調用的服務實例
2. 執行選出的實例
3. 執行實例成功即返回,失敗拋出RpcException異常
FailsafeCluster:安全失敗
場景:調用失敗后忽略
配置:
代碼實現邏輯
1. 根據負載均衡策略選出需要調用的服務實例
2. 執行選出的實例
3. 執行實例成功即返回,失敗輸出error日志,并返RpcResult,視為忽略。
ForkingCluster:并發處理
場景:并發調用指定數量的服務,一個成功則返回,對實時性要求高的場景,要求快速返回,需要使用更多服務器資源。
配置:
代碼實現邏輯
1. 根據負載均衡策略選出幾個不同的服務實例
2. 并發執行選出的幾個實例,并將返回結果放入堵塞隊列中
3. 返回堵塞隊列中的第一個值,如規定時間內未獲取到隊列中的值或獲取到異常值則返回RPC異常。
BroadcastCluster:廣播
場景:廣播方式逐個調用服務提供者,有一個報錯則返回錯誤,多用于通知服務提供者更新本地資源信息,如緩存,日志等。
配置:
代碼實現邏輯
1. 循環逐個執行所有服務實例信息
2. 保存一份返回結果和異常信息
3. 執行完全部實例后,如異常信息不為空,則拋出異常信息,否則返回最后一個實例的結果。
AvailableCluster:可用服務
場景:調用第一個可用服務
配置:
代碼實現邏輯
1. 循環所有服務實例信息
2. 執行第一個可用的實例,并返回結果
3. 如無可用實例則返回RpcException異常
MergeableCluster:合并處理
場景:返回合并或疊加處理結果
配置:
代碼實現邏輯
1. 判斷merger,為空、null、0、false、N/A是執行第一個可用服務并返回結果,無可用則執行第一個實例,并返回結果。
2. 獲取方法實例的返回類型
3. 異步調用所有實例,并將異步結果Result存儲到結果集中,返回異常輸出error日志
4. 結果集為空返回 RpcException,大小為 1時返回第一個Result
5. 當merger的第一個字符為“.”時,判斷當 merger 實例返回類型不為void,且返回類型必須是結果集中第一個返回類型的父類型或相同類型時,循環執行merger實例,每一次都傳入上一次的返回結果,最終返回獲取最后一次結果,非上述情況時循環執行merger實例,返回結果集中的第一個結果。
6. 當merger為true或default時使用Dubbo默認合并器,否則使用自定義merger合并器,合并后返回
RegistryAwareCluster:默認標識、注冊標識
場景:調用注冊默認標識的服務
配置:
代碼實現邏輯
1.8 循環所有服務實例信息
2. 執行第一個可用的實例且default為true的實例
3. 無默認實例則執行第一個可用的實例
4. 無可用的實例則拋出RpcException異常
主要配置
配置應用信息:
<dubbo:application?name=“appName-provider”?/>配置注冊中心相關信息:
<dubbo:registryid=“zk”?protocol=“zookeeper”?address=“127.0.0.1:2181”?/>配置服務協議:
<dubbo:protocol?name=“dubbo”?port=“20880”?threadpool=“cached”?threads=“80”?/>配置所有暴露服務缺省值:
<dubbo:provider?registry=“zk”?protocol=“dubbo”?retries=“0”?version=“1.0.0”?timeout=“3000”?threadpool=“cached”?threads=“4”/>配置暴露服務:
<dubbo:service?interface=“com.orgname.app.serviceX”?ref=“serviceX”?/>配置所有引用服務缺省值:
<dubbo:consumer?check=“false”?timeout=“1000”?version=“1.0”?retries=“0”?async=“false”?/>注解配置:
com.alibaba.dubbo.config.annotation.Service?配置暴露服務com.alibaba.dubbo.config.annotation.Reference配置引用服務?
?
超時設置
Dubbo消費端
全局超時配置
<dubbo:consumer?timeout="5000"?/>指定接口以及特定方法超時配置
<dubbo:reference?interface="com.foo.BarService"?timeout="2000"><dubbo:method?name="sayHello"?timeout="3000"?/> </dubbo:reference>Dubbo服務端
全局超時配置
<dubbo:provider?timeout="5000"?/>指定接口以及特定方法超時配置
<dubbo:provider?interface="com.foo.BarService"?timeout="2000"><dubbo:method?name="sayHello"?timeout="3000"?/> </dubbo:provider>?
?
支持協議
1、Dubbo 協議(官方推薦協議)
優點:采用NIO復用單一長連接,并使用線程池并發處理請求,減少握手和加大并發效率,性能較好(推薦使用)
缺點:大文件上傳時,可能出現問題(不使用 Dubbo 文件上傳)
2、RMI(Remote Method Invocation)協議
優點:JDK 自帶的能力。可與原生 RMI 互操作,基于 TCP 協議
缺點:偶爾連接失敗.
3、Hessian協議
優點:可與原生 Hessian 互操作,基于 HTTP 協議
缺點:需 hessian.jar 支持,http 短連接的*開銷大8
常用設計模式
Dubbo 框架在初始化和通信過程中使用了多種設計模式,可靈活控制類加載、權限控制等功能。
工廠模式
Provider 在 export 服務時,會調用 ServiceConfig 的 export 方法。ServiceConfig 中有個字段:
private?static?final?Protocol?protocol?= ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();Dubbo 里有很多這種代碼。這也是一種工廠模式,只是實現類的獲取采用了 JDK SPI 的機制。這么實現的優點是可擴展性強,想要擴展實現,只需要在 classpath下增加個文件就可以了,代碼零侵入。另外,像上面的 Adaptive 實現,可以做到調用時動態決定調用哪個實現,但是由于這種實現采用了動態代理,會造成代碼調試比較麻煩,需要分析出實際調用的實現類。
裝飾器模式
Dubbo 在啟動和調用階段都大量使用了裝飾器模式。以 Provider 提供的調用鏈為例,具體的調用鏈代碼是在 ProtocolFilterWrapper 的buildInvokerChain 完成的,具體是將注解中含有 group=provider 的 Filter 實現,按照 order 排序,最后的調用順序是:
EchoFilter?->?ClassLoaderFilter?->?GenericFilter?->?ContextFilter?-> ExecuteLimitFilter?->?TraceFilter?->?TimeoutFilter?->?MonitorFilter?-> ExceptionFilter更確切地說,這里是裝飾器和責任鏈模式的混合使用。例如,EchoFilter 的作用是判斷是否是回聲測試請求,是的話直接返回內容,這是一種責任鏈的體現。而像ClassLoaderFilter 則只是在主功能上添加了功能,更改當前線程的 ClassLoader,這是典型的裝飾器模式。
觀察者模式
Dubbo 的 Provider 啟動時,需要與注冊中心交互,先注冊自己的服務,再訂閱自己的服務,訂閱時,采用了觀察者模式,開啟一個 listener。注冊中心會每 5 秒定時檢查是否有服務更新,如果有更新,向該服務的提供者發送一個 notify 消息,provider 接受到 notify 消息后,即運行 NotifyListener 的 notify 方法,執行監聽器方法。
動態代理模式
Dubbo 擴展 JDK SPI 的類 ExtensionLoader 的 Adaptive 實現是典型的動態代理實現。Dubbo 需要靈活地控制實現類,即在調用階段動態地根據參數決定調用哪個實現類,所以采用先生成代理類的方法,能夠做到靈活的調用。生成代理類的代碼是 ExtensionLoader 的 createAdaptiveExtensionClassCode 方法。代理類的主要邏輯是,獲取 URL 參數中指定參數的值作為獲取實現類的 key
工作流程
整體流程:
第一步:provider 向注冊中心去注冊
第二步:consumer 從注冊中心訂閱服務,注冊中心會通知 consumer 注冊好的服務
第三步:consumer 調用 provider
第四步:consumer 和 provider 都異步通知監控中心
流程圖
?
?
總結
最后用一張圖來形象的模擬 Dubbo 的使用:
使用
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的微服务面试必问的Dubbo,这么详细还怕自己找不到工作?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 聊聊redo log是什么?
- 下一篇: 为什么计算机中0.2+0.1不等于0.3