dubbo深刻學習的一些總結

 

Dubbo 源文件主要包含以上這麼多包,其中:java

首先對dubbo-2.8.4.jar 源碼的一個截圖spring

dubbo-common

公共邏輯模塊,包括 Util 類和通用模型。網絡

dubbo-remoting

遠程通信模塊,至關於 Dubbo 協議的實現,若是 RPC 用 RMI 協議 則不須要使用此包。併發

Dubbo缺省協議採用單一長鏈接和NIO異步通信,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的狀況。app

缺省協議,使用基於netty3.2.2+hessian3.2.1交互。

    鏈接個數:單鏈接
    鏈接方式:長鏈接
    傳輸協議:TCP
    傳輸方式:NIO異步傳輸
    序列化:Hessian二進制序列化
    適用範圍:傳入傳出參數數據包較小(建議小於100K),消費者比提供者個數多,單一消費者沒法壓滿提供者,儘可能不要用dubbo協議傳輸大文件或超大字符串。
    適用場景:常規遠程服務方法調用負載均衡

一、爲何要消費者比提供者個數多
    因dubbo協議採用單一長鏈接,
    假設網絡爲千兆網卡(1024Mbit=128MBytae),
    根據測試經驗數據每條鏈接最多隻能壓滿7MByte(不一樣的環境可能不同,供參考),
    理論上1個服務提供者須要20個服務消費者才能壓滿網卡。異步

二、爲何不能傳大包
    因dubbo協議採用單一長鏈接,若是每次請求的數據包大小爲500KByte,假設網絡爲千兆網卡(1024Mbit=128MByte),每條鏈接最大7MByte(不一樣的環境可能不同,供參考),
    單個服務提供者的TPS(每秒處理事務數)最大爲:128MByte / 500KByte = 262。
    單個消費者調用單個服務提供者的TPS(每秒處理事務數)最大爲:7MByte / 500KByte = 14。
    若是能接受,能夠考慮使用,不然網絡將成爲瓶頸。ide

爲何採用異步單一長鏈接:
    由於服務的現狀大都是服務提供者少,一般只有幾臺機器, 而服務的消費者多,可能整個網站都在訪問該服務,
    好比Morgan的提供者只有6臺提供者,卻有上百臺消費者,天天有1.5億次調用, 若是採用常規的hessian服務,服務提供者很容易就被壓跨, 經過單一鏈接,保證單一消費者不會壓死提供者,長鏈接,減小鏈接握手驗證等,
並使用異步IO,複用線程池,防止C10K問題。函數

約束:測試

 參數及返回值需實現Serializable接口

參數及返回值需有無參構造函數(能夠是private的)或者有參構造全部函數容許傳入null值。

參數及返回值不能自定義實現List, Map, Number, Date, Calendar等接口,只能用JDK自帶的實現,由於hessian會作特殊處理,自定義實現類中的屬性值都會丟失。
Hessian序列化,只傳成員屬性值和值的類型,不傳方法或靜態變量,兼容狀況:

 數據通信     狀況     結果
    A->B     類A多一種 屬性(或者說類B少一種 屬性)     不拋異常,A多的那 個屬性的值,B沒有, 其餘正常
    A->B     枚舉A多一種 枚舉(或者說B少一種 枚舉),A使用多 出來的枚舉進行傳輸     拋異常
    A->B     枚舉A多一種 枚舉(或者說B少一種 枚舉),A不使用 多出來的枚舉進行傳輸     不拋異常,B正常接 收數據
    A->B     A和B的屬性 名相同,但類型不相同     拋異常
    A->B     serialId 不相同     正常傳輸

dubbo-rpc

遠程調用模塊,抽象各類協議,以及動態代理,只包含一對一的調用, 不關心集羣的管理。

dubbo-cluster

集羣模塊,將多個服務提供方假裝爲一個提供方,包括:負載均衡, 容 錯,路由等,集羣的地址列表能夠是靜態配置的,也能夠是由註冊中心下發。

dubbo-monitor

監控模塊,統計服務調用次數,調用時間的,調用鏈跟蹤的服務。

dubbo-container 

容器模塊,是一個 Standlone 的容器,以簡單的 Main 加載 Spring 啓動,由於服務一般不須要 Tomcat/JBoss 等 Web 容器的特性,不必用 Web 容器去加 載服務。

服務容器只是一個簡單的Main方法,並加載一個簡單的Spring容器,用於暴露服務。 

服務容器的加載內容能夠擴展,內置了spring, jetty, log4j等加載,可經過Container擴展點進行擴展

Container 包含:Spring Container    Jetty Container   Log4j Container

簡單介紹一下Spring Container的使用  

    1)自動加載META-INF/spring目錄下的全部Spring配置。 

    或者  2)配置:(配在java命令-D參數或者dubbo.properties中) 
        dubbo.spring.config=classpath*:META-INF/spring/*.xml ----配置spring配置加載位置 

默認缺省加載Spring Container 緣由:

在dubbo-2.8.4.jar中  在META-INT/dubbo/internal/com.alibba.dubbo.container.Container

spring=com.alibaba.dubbo.container.spring.SpringContainer  有此配置!!!

代碼:

/** 
* 主線程啓動 
*/ 
public class TestMain { 

    public static void main(String[] args) throws Exception { 
        com.alibaba.dubbo.container.Main.main(args); 
    } 

dubbo-registry

註冊中心模塊,基於註冊中心下發地址的集羣方式,以及對各類注 冊中心的抽象。

對於服務提供方,它須要發佈服務,並且因爲應用系統的複雜性,服務的數量、類型也不斷膨脹;對於服務消費方,它最關心如何獲取到它所須要的服務,而面對複雜的應用系統,須要管理大量的服務調用。並且,對於服務提供方和服務消費方來講,他們還有可能兼具這兩種角色,即既須要提供服務,有須要消費服務。
經過將服務統一管理起來,能夠有效地優化內部應用對服務發佈/使用的流程和管理。服務註冊中心能夠經過特定協議來完成服務對外的統一。Dubbo提供的註冊中心有以下幾種類型可供選擇:

  • Multicast註冊中心
  • Zookeeper註冊中心
  • Redis註冊中心
  • Simple註冊中心
  • default註冊中心即爲dubbo-2.8.4.jar 中com.dubbo.registry.dubbo.*

服務首先暴露在服務端,而後調用Registry的register方法在註冊中心(它是一個服務協調中心,dubbo之外的獨立服務端,dubbo提供了客戶端實現)註冊服務,而後用戶經過配置文件中配置的service的url去subscribe(訂閱服務),Registry接收到訂閱消息後會往url對應的的List<NotifyListener>中塞入當前NotifyListener,反之從這個list中移除listener就是取消訂閱。registry會調用據consumer的訂閱狀況調用notify方法推送服務列表給Consumer。

Provider初始化時會調用doRegister方法向註冊中心發起註冊。那麼客戶端又是怎麼subscribe在註冊中心訂閱服務的呢?答案是服務消費者在初始化ConsumerConfig時會調用RegistryProtocol的refer方法進一步調用RegistryDirectory的subscribe方法最終調用ZookeeperRegistry的subscribe方法向註冊中心訂閱服務。

注意:

看以下配置發佈服務:

<dubbo:registry protocol=」dubbo」 address="127.0.0.1:9090" />

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" protocol=」dubbo」  />

1. 指定了哪一種的註冊中心,是基於dubbo協議的,指定了註冊中心的地址以及端口號

2. 發佈DemoService服務,服務的實現爲DemoServiceImpl

每一個<dubbo:service/>在spring內部都會生成一個ServiceBean實例,ServiceBean的實例化過程當中調用export方法來暴露服務

1. 經過loadRegistries獲取註冊中心registryUrls

registry://127.0.0.1:9090/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT&owner=william&pid=7084&registry=dubbo&timestamp=1415711791506

用統一數據模型URL表示:

protocol=registry表示一個註冊中心url

註冊中心地址127.0.0.1:9090

調用註冊中心的服務RegistryService

註冊中心協議是registry=dubbo

2. 構建發佈服務的URL

dubbo://192.168.0.102:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7084&side=provider&timestamp=1415712331601

發佈協議protocol =dubbo

服務提供者的地址爲192.168.0.102:20880

發佈的服務爲com.alibaba.dubbo.demo.DemoService

3. 遍歷registryUrls向註冊中心註冊服務

給每一個registryUrl添加屬性key爲export,value爲上面的發佈服務url獲得以下registryUrl

registry://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT& export=dubbo%3A%2F%2F192.168.0.102%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D2.5.4-SNAPSHOT%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26loadbalance%3Droundrobin%26methods%3DsayHello%26owner%3Dwilliam%26pid%3D7084%26side%3Dprovider%26timestamp%3D1415712331601&owner=william&pid=7084&registry=dubbo&timestamp=1415711791506

4. 由發佈的服務實例,服務接口以及registryUrl爲參數,經過代理工廠proxyFactory獲取Invoker對象,Invoker對象是dubbo的核心模型,其餘對象都向它靠攏或者轉換成它。

5. 經過Protocol對象暴露服務protocol.export(invoker)

經過DubboProtocol暴露服務的監聽(不是此節內容)

經過RegistryProtocol將服務地址發佈到註冊中心,並訂閱此服務

RegistryProtocol.export(Invoker)暴露服務

消費者引用服務

< dubbo:registry protocol = 」dubbo」 address = "127.0.0.1:9098" />

< dubbo:reference id = "demoService" interface = "com.alibaba.d ubbo.demo.DemoService" />

1. 指定了哪一種的註冊中心,是基於dubbo協議的,指定了註冊中心的地址以及端口號

2. 引用遠程DemoService服務

每一個<dubbo:reference/>標籤spring加載的時候都會生成一個Referenc eBean。

如上圖ReferenceBean實現了spring的FactoryBean接口, 實現了此接口的Bean經過spring的BeanFactory.getBean(「beanName」)獲取的對象不是配置的bean自己而是經過FactoryBean.getObject()方法返回的對象,此接口在spring內部被普遍使用,用來獲取代理對象等等。這裏getObjec t方法用來生成對遠程服務調用的代理

1. loadRegistries()獲取配置的註冊中心的registryUrls

2. 遍歷registryUrls集合,給registryUrl加上refer key就是要引用的遠程服務

[ registry ://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.0&pid=2484& refer =application%3Ddemo-consumer%26dubbo%3D2.0.0%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DsayHello%26pid%3D2484%26side%3Dconsumer%26timestamp%3D1415879965901&registry=dubbo&timestamp=1415879990670]

3. 遍歷registryUrls集合,使用Protocol.refer(interface,regist ryUrl)的到可執行對象invoker

4. 若是註冊中心有多個的話, 經過集羣策略Cluser.join()將多個invoke r假裝成一個可執行invoker, 這裏默認使用available策略

5. 利用代理工廠生成代理對象proxyFactory.getProxy(invoker)

基於 Spring 可擴展 Schema 提供自定義配置支持(spring 配置文件中 配置標籤支持) 

以上標籤

未完待續.........

相關文章
相關標籤/搜索