當前位置:首頁 » 操作系統 » dubbo源碼解析

dubbo源碼解析

發布時間: 2022-12-30 13:34:22

① 14. bbo源碼-集群容錯之MergeableCluster

在bbo官方的用戶手冊中,提到了使用 MergeableCluster 的場景--分組聚合:

功能示意圖如下:

定義菜單介面方式:

Provider暴露服務--一個服務屬於 group-hot ,一個服務屬於 group-cold

筆者測試時啟動了兩個Provider,所以總計有四個服務,bbo-monitor監控顯示如下:

Consumer調用服務:

幾個重要的配置說明:

com.alibaba.bbo.rpc.cluster.Merger 文件內容如下:

核心源碼在 MergeableClusterInvoker.java 中,源碼如下所示:

在條件分支 if ( merger.startsWith(".") ) {} 中,有一段邏輯: method = returnType.getMethod( merger, returnType ); ,即從bbo服務介面方法返回類型即 java.util.List 中查找merger配置的方法,例如 .addAll ,我們先看一下debug過程各變數的值:

bbo源碼中 method = returnType.getMethod( merger, returnType ); 調用 Method method = getMethod0(name, parameterTypes, true); ,再調用 Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates); ,最後調用 searchMethods(privateGetDeclaredMethods(true), name, parameterTypes)) ,得到最後方法匹配的核心邏輯如下:

從searchMethods()源碼可知,方法匹配需要滿足幾個條件:

由上面的分析可知,如果要merger=".addAll"能夠正常工作,那麼只需要將bbo服務的返回類型改成 Collection 即可,例如:

如果 com.alibaba.bbo.rpc.cluster.Merger 文件集中方法無法滿足需求,需要自定義實現,那麼還是和bbo其他擴展實現一樣,依賴SPI。只需要一下幾步實現即可:

② Dubbo啟動源碼解析一

這次講 bbo-spring-boot-starter 啟動方式,所以入口就是Spring的SPI機制;
首先在META-INF/spring.factories配置下,配置了org.apache.bbo.spring.boot.autoconfigure.DubboAutoConfiguration類,在啟動時,則會把DubboAutoConfiguration類注冊到spring容器中;
我們來看下DubboAutoConfiguration
先看啟動流程

我們先看下生產者端的啟動流程,首先是在Spring中注冊類

該類實現了介面,則在Spring容器初始化時,會調用方法

我們會看到,這個時候會去注冊類,這個類我們等流程到了在分析,我們先按啟動流程看過去;resolvePackagesToScan方法先獲取到需要掃描的包 ,然後再調用registerServiceBeans去注冊相關實例,我們重點來看下registerServiceBeans方法

接下來,我們主要去看下registerServiceBean方法

接下來,我們來看下buildServiceBeanDefinition方法

到這,ServiceBean注冊成功,ServiceBean類很重要,每個Dubbo service實例都對應一個ServiceBean,相關配置都在ServiceBean中;我們再回到開始注冊的類

類繼承了,實現了ApplicationListener,主要監聽了Spring容器生命周期,我們看下onApplicationContextEvent方法

我們可以看到,當Spring容器啟動成功時,會調用bboBootstrap.start();

接下來,主要邏輯在ServiceBean中,這個export方法在其父類ServiceConfig中,我們下一篇主要講ServiceConfig邏輯;

③ Dubbo之限流分析

在前面的一篇中分析了Dubbo是如何降級的,除了降級,有時限流也是一種很有效的解決高並發的性能問題,那在本篇中開始分析Dubbo是如何限流的。我們知道限流主要是通過控制連接數來實現的,防止某一片段內請求處理過大,導致重要服務的失效。

服務端連接控制

限制當前提供者在使用bbo協議最多接受10個消費者鏈接

或者

並發控制
限制 com.foo.BarService 的每個方法,服務端並發執行(或佔用線程池線程數)不能超過10個:

限制 com.foo.BarService 的 sayHello 方法,伺服器並發執行(或佔用線程池線程數)不能超過10個。

actives限流

該限流方式與前兩種不同,其可以設置在提供端,也可以設置在消費者端。可以設置為介面級別,也可以設置為方法級別。
根據消費者與提供者建立的連接類型,其意義也不同。

長連接 : 表示當前的長連接最多可以處理的請求個數。與長連接的數量沒有問題。
短連接 :表示當前服務可以同時處理的短連接數量。
類級別

方法級別

connections限流

可以設置在提供端,也可以設置在消費者端。限定連接的個數。對於短連接,和actives相同。但對於長連接,表示長連接的個數。
一般情況下,會使connections與actives聯用,讓connections限制長連接的個數,讓actives限制長連接中可以處理的請求個數。
限制客戶端服務使用連接不能超過10個

如果 <bbo:service> 和 <bbo:reference> 都配置了connections, <bbo:reference> 優先。

延遲連接

延遲連接僅可以設置在消費者端,並且不能設置為方法級別。僅作用於Dubbo服務暴露協議。將長連接的建立推遲到消費者真正調用提供者時。 可以減少長連接的數量。

我們已經講解了如何設置控制鏈接數的,那麼它們底層是如何實現的呢?

實際上上面的邏輯都是一個個Filter,所有的Filter會連接成一個過濾器鏈,每次請求都會經過整個鏈路中的每一個Filter。那它是在什麼時候構造成一個過濾器鏈的呢。

在服務暴露的時候會調用 buildInvokerChain , 將真正執行的 invoker 放到過濾鏈的尾部,再執行 protocol.expert(buildInvokerChain(invoker, ...)) 方法來進行服務暴露。

在服務引用的時候會調用 protocol.refer() 方法先生成 Invoker ,再調用 buildInvokerChain(protocol.refer(type, url), ...) 來生成消費類型的調用鏈。

ExecuteLimitFilter

它用於限制每個服務中每個方法的最大並發數,有介面級別和方法級別的配置方式

其基本原理:在框架中使用一個ConcurrentMap緩存了並發數的計數器,為每個請求URL生成一個IdentityString,並以此為key;再將每個IdentityString生成一個RpcStatus對象,將此作為value。RpcStatus對象用於記錄對應的並發數。在調用開始之前,會通過URL獲得RpcStatus對象,把對象中的並發數計數器原子+1,在finally中再將原子減1。只要在計數器+1的時候,發現當前計數器比設置的並發數大時,就會拋出異常。

TpsLimitFilter

TpsLimitFilter的限流是基於令牌的,即一段時間內只分配N個令牌,每次請求都會消耗一個令牌,耗完為止,後面再來的請求都會被拒絕。
具體的邏輯是在 DefaultTPSLimiter#isAllowable ,會用這個方法判斷是否觸發限流。
在DefaultTPSLimiter內部用一個ConcurrentHashMap緩存每個介面的令牌數,key是interface+group+version,value是一個StatItem對象,它包裝了令牌刷新時間間隔、每次發放的令牌數等。首先判斷當前時間減去上次發放令牌的時間是否超過了時間間隔,超過了就重新發放令牌,之前剩餘的令牌會被直接覆蓋掉。然後,通過CAS的方式減去1令牌,減掉後小於0就會觸發限流。

ActiveLimitFilter

和服務提供者的 ExecuteLimitFilter 相似,它是消費者端的過濾器,限制的是客戶端的並發量。

但是它與 ExecuteLimitFilter 有所不同,它不會直接拋出異常。而是當到達閾值的時候,會先加鎖搶占當前介面的RpcStatus對象,然後通過wait方法進行等待,等待是有時間的,因為請求是有 timeout 屬性的。然後如果某個Invoker在調用結束後,並發把計數器減-1並觸發一個notify,此時會有一個在wait狀態的線程被喚醒並繼續執行,判斷現在是否超時,如果超時則拋出異常。如果當前並發數仍然超出閾值,則繼續執行wait方法;如果沒有超出閾值在,則跳出循環,CAS+1,並調用invoke方法,調用結束後CAS-1,最後通過notify喚醒另外一個線程。

參考文章:
Dubbo之限流TpsLimitFilter源碼分析
Dubbo服務限流
Dubbo源碼分析----過濾器之ActiveLimitFilter

④ 【bbo源碼】5.配置信息解析-註解版

用於把bbo.properties讀到spring的environment中,

這個工作是由Spring的類來完成的.檢測到某個需要注冊的Bean上有@PropertySource註解,就會讀該文件的配置信息,弄到environment對象的MutablePropertySources對象中。

後期會把配置信息弄到bbo 配置類中.

該註解上還有@DubboComponentScan,@EnableDubboConfig,這兩個註解是bbo用註解與spring集成的核心了

該註解用@import導入了這個類

實現了ImportBeanDefinitionRegistrar介面,那麼spring在實例化的時候會調用重寫ImportBeanDefinitionRegistrar介面的registerBeanDefinitions方法,並且將用@Import導入的類的元數據包裝成importingClassMetadata對象。

其實就是為了獲取入口類AnnoBean上的@EnableDubboConfig註解里的multiple屬性配置的值,默認是true.

然後注冊了兩個DubboConfigConfiguration的內部類

通過讀Class對象注冊到ioc容器

類上有@EnableDubboConfigBindings,值為@EnableDubboConfigBinding數組
通過綁定,將有對應前綴的配置信息賦值到對應的配置類中

又用@Import導入DubboConfigBindingsRegistrar類,DubboConfigBindingsRegistrar這個類又實現了ImportBeanDefinitionRegistrar,EnvironmentAware介面

實現ImportBeanDefinitionRegistrar肯定是為了另外導入一些類,並且拿到導入的源類,獲取源類上配置的信息

實現EnvironmentAware是為了拿到spring的environment對象,因為 bbo.properties 已經被@PropertySource註解機制載入到了environment.MutablePropertySources中,在這里只對beanName的創建有作用。

registrar.registerBeanDefinitions :

注冊的過程中,需要從environment對象中拿bbo相關的配置,比如ApplicationConfig只拿
bbo.application.*相關的配置,然後創建ApplicationConfig的BeanDefinition.

如果 @EnableDubboConfigBinding配置的multiple為true(默認為false),並且在配置文件中配置了同樣前綴的屬性,如:

這樣會為同一種配置類型,生成兩個BD.beanName不同的配置Bean,名稱規則如下所示, #0表示的是'.'在配置的key中出現的位置

之後還會注冊一個BeanPostProcessor類型的類的beanDefinition,BeanPostProcessor類型 會在每一個Bean實例化的過程中,根據配置的前綴,從environment拿出所需的配置,根據beanName來處理beanName相同的這一個配置Bean,把配置信息綁定到配置類的屬性中。

.

利用 bboConfigBinder 對象來綁定前綴為bbo.application的配置信息到配置Bean中

這里bboConfigBinder對象是中的一個屬性,是在因為這個類實現了InitializingBean這個介面的afterPropertiesSet方法,bboConfigBinder對象就是在這里初始化的

最後用的DataBinder的api把一個MutablePropertyValues綁定到Bean的屬性

@import進來了DubboComponentScanRegistrar類

DubboComponentScanRegistrar又實現了ImportBeanDefinitionRegistrar介面,實現registerBeanDefinitions方法.

跟xml的邏輯一樣,同樣是

熱點內容
長虹安卓電視關閉網路在哪裡 發布:2025-05-10 14:37:04 瀏覽:141
ubuntuhttp伺服器的搭建 發布:2025-05-10 14:33:06 瀏覽:36
微信找回密碼申訴要多少時間 發布:2025-05-10 14:14:05 瀏覽:435
大眾寶來速騰選哪個配置 發布:2025-05-10 14:10:53 瀏覽:128
數字機頂盒密碼是多少 發布:2025-05-10 14:10:06 瀏覽:334
取消訪問網路需要密碼 發布:2025-05-10 13:44:20 瀏覽:64
shell編程運行 發布:2025-05-10 13:37:54 瀏覽:640
win7訪問xp共享需要密碼 發布:2025-05-10 13:34:10 瀏覽:344
飯團看書為什麼緩存不了小說 發布:2025-05-10 13:17:03 瀏覽:13
如何配置登錄源地址限制 發布:2025-05-10 13:12:52 瀏覽:591