Dubbo原碼解析(version:2.5.3)

1、啓動
dubbo藉助spring的schemas來啓動(dubbo.jar/META-INF/spring.schemas)。
在dubbo.jar/META-INF/spring.handlers裏配置了dubbo bean的解析類DubboNamespaceHandler。主要的有ServiceBean.java和ReferenceBean.java。html

 

2、Dubbo Bean的註冊(DubboBeanDefinitionParser.java)
DubboBeanDefinitionParser.parse():將咱們在beans-dubbo.xml裏面配置的 bean 進行解析(包括dubbo的配置,ServiceBean和ReferenceBean),而後註冊到Spring容器中,給Spring託管。
例如:beans-dubbo.xml有以下配置java

<dubbo:application name="#{dubboConfig.applicationName}" owner="#{dubboConfig.applicationOwner}" />
<dubbo:registry address="#{dubboConfig.registryAddress}" />
<dubbo:protocol name="#{dubboConfig.protocolName}" port="#{dubboConfig.protocolPort}" />
<dubbo:provider retries="0" timeout="10000" />
<dubbo:consumer check="false" />
<dubbo:service interface="com.tz.agent.job.IAccountNettingTask" ref="accountNettingTask" />
<dubbo:reference id="accountQueryService" interface="com.basizbiz.account.service.IAccountQueryService"/>

dubbo.properties配置:web

dubbo.application.name=tz-agent
dubbo.application.owner=tf
dubbo.registry.address=zookeeper://192.168.xx.44:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20910
View Code

容器裏面相關的bean name以下:(parserContext.getRegistry().getBeanDefinitionNames()的結果)redis

accountNettingTask, #{dubboConfig.applicationName}, com.alibaba.dubbo.config.RegistryConfig, #{dubboConfig.protocolName},
com.alibaba.dubbo.config.ProviderConfig, com.alibaba.dubbo.config.ConsumerConfig, com.tz.agent.job.IAccountNettingTask, accountQueryService

1. 第一個accountNettingTask是Spring @Service註解產生的bean。算法

2. com.ihome.tz.agent.job.IAccountNettingTask是dubbo配置文件裏面定義的ServiceBean。spring

3. accountQueryService是dubbo配置文件裏面定義的ReferenceBean。api

能夠看出,Provider端生產了兩種bean,一種是@Service的bean,還有一種是dubbo export的bean。併發

 

3、Provider端暴露服務
ServiceBean.afterPropertiesSet()方法最終會作服務暴露export();
拼裝dubbo的URL --> protocol.export(invoker) --> ProtocolFilterWrapper.export() --> protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER))
buildInvokerChain()會將知足條件的Filter層層包裝在Invoker上。好比:ExceptionFilter、ValidationFilter、EchoFilter....app

暴露的URL形如:
dubbo://192.168.xx.11:20910/com.tz.agent.job.IHistoryShareInitJob?anyhost=true&application=tz-agent&default.retries=0&default.timeout=10000&dubbo=2.5.3&interface=com.ihome.tz.agent.job.IHistoryShareInitJob&methods=initByExcel&owner=tf&pid=9596&revision=0.0.2-SNAPSHOT&side=provider&timestamp=1490688484344
負載均衡


4、Consumer端引用服務
ReferenceBean.afterPropertiesSet()方法最終會調ReferenceBean.createProxy()給ref賦值。
proxyFactory.getProxy(invoker) --> JavassistProxyFactory.getProxy()
ref的實例持有一個new InvokerInvocationHandler(invoker)對象。
------------------------
refprotocol.refer() --> ProtocolFilterWrapper.refer() --> buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER)

 引用的URL形如:
dubbo://10.166.xx.85:20899/com.biz.product.service.ISharesQueryService?anyhost=true&application=tz-agent&check=false&default.check=false&default.retries=0&default.timeout=10000&dubbo=2.5.3&interface=com.ihome.biz.product.service.ISharesQueryService&methods=queryProduct,queryByDate,queryBenefitAccount,queryProductByBizProductCode,queryBizProductSelect,queryAllProductList,queryProductByBenefitCode,queryBizProductPage&owner=tf&pid=12772&revision=0.0.5-SNAPSHOT&side=consumer&timestamp=1490688712775

 

 

附:Dubbo SPI :

Dubbo SPI是Dubbo留的擴展點

例如Dubbo的Protocal就是經過dubbo SPI 來擴展的。 ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort()

Dubbo SPI 加載文件

ExtensionLoader.loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
ExtensionLoader.loadFile(extensionClasses, DUBBO_DIRECTORY);
ExtensionLoader.loadFile(extensionClasses, SERVICES_DIRECTORY);

 

【1】
dubbo-2.5.3.jar\META-INF\dubbo\internal\com.alibaba.dubbo.common.extension.ExtensionFactory

adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

針對文件中的類:
帶有@Adaptive 的放到 cachedAdaptiveClass 中,有參數爲ExtensionFactory的構造函數的放到 cachedWrapperClasses 中,不然放到 cachedClasses 中

-->
public T getAdaptiveExtension() 優先取 cachedAdaptiveClass.newInstance(),即 AdaptiveExtensionFactory
不然,會動態編譯代碼 String code = createAdaptiveExtensionClassCode();,使用AdaptiveExtensionFactory.getExtension(Class<T> type, String name)拿到適配的Extension

【2】
dubbo-2.5.3.jar\META-INF\dubbo\internal\com.alibaba.dubbo.rpc.Protocol
======================
registry=com.alibaba.dubbo.registry.integration.RegistryProtocol        --- 放到 cachedClasses
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper           --- 放到 cachedWrapperClasses (ref時將Filter裝飾在)
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper       --- 放到 cachedWrapperClasses
mock=com.alibaba.dubbo.rpc.support.MockProtocol
injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol            --- 放到 cachedClasses
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol          --- 放到 cachedClasses
rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol              --- 放到 cachedClasses
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol         --- 放到 cachedClasses
com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
memcached=memcom.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol
======================

 

 

Dubbo中的特性和坑:

1. Dubbo的異步具備傳遞性。(移除異步:RpcContext.getContext().getAttachments().remove(com.alibaba.dubbo.common.Constants.ASYNC_KEY);

2. Dubbo Hessian序列化問題 參數爲null

3. Dubbo 支持 telnet

4. Dubbo 支持泛化調用

 

 

Dubbo配置:

注意:
dubbo中全部配置項分爲三大類:
1. 【服務發現】參數:表示該配置項用於服務的註冊與發現,目的是讓消費方找到提供方。
2. 【服務治理】參數:表示該配置項用於治理服務間的關係,或爲開發測試提供便利條件。
3. 【性能調優】參數:表示該配置項用於調優性能,不一樣的選項對性能會產生影響。

只有interface,group,version是服務的匹配條件,用於服務發現,三者決定是否是同一個服務,其它配置項均爲服務調優和服務治理參數。

http://dubbo.io/user-guide/reference-xmlconf/introduction.html

 

配置推薦用法

在Provider上儘可能多配置Consumer端屬性

緣由以下:

  1. 做服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間,合理的重試次數,等等
  2. 在Provider配置後,Consumer不配置則會使用Provider的配置值,即Provider配置能夠做爲Consumer的缺省值。

不然,Consumer會使用Consumer端的全局設置,這對於Provider不可控的,而且每每是不合理的

配置的覆蓋規則:

1) 方法級配置別優於接口級別,即小Scope優先

2) Consumer端配置 優於 Provider配置 優於 全局配置,最後是Dubbo Hard Code的配置值(見配置文檔)

Provider上儘可能多配置Consumer端的屬性,讓Provider實現者一開始就思考Provider服務特色、服務質量的問題。

示例:

< dubbo:service interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" ref = "helloService"
     timeout = "300" retry = "2" loadbalance = "random" actives = "0"
/>
 
< dubbo:service interface = "com.alibaba.hello.api.WorldService" version = "1.0.0" ref = "helloService"
     timeout = "300" retry = "2" loadbalance = "random" actives = "0" >
     < dubbo:method name = "findAllPerson" timeout = "10000" retries = "9" loadbalance = "leastactive" actives = "5" />
< dubbo:service />

在Provider能夠配置的Consumer端屬性有:

    1. timeout,方法調用超時
    2. retries,失敗重試次數,缺省是2(表示加上第一次調用,會調用3次)
    3. loadbalance,負載均衡算法(有多個Provider時,如何挑選Provider調用),缺省是隨機(random)。
      還能夠有輪訓(roundrobin)、最不活躍優先(leastactive,指從Consumer端併發調用最好的Provider,能夠減小的反應慢的Provider的調用,由於反應更容易累積併發的調用)
    4. actives,消費者端,最大併發調用限制,即當Consumer對一個服務的併發調用到上限後,新調用會Wait直到超時。在方法上配置(dubbo:method )則併發限制針對方法,在接口上配置(dubbo:service),則併發限制針對服務。
相關文章
相關標籤/搜索