dubbo版本:2.5.4
服務發布是服務提供方向注冊中心注冊服務過程,以便服務消費者從注冊中心查閱並調用服務。
服務發布方在spring的配置文件中配置如下:
<bean id="demoService"class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />
上面是在spring中配置的服務的具體實現,是spring中的一個普通的bean。
<dubbo:serviceinterface="com.alibaba.dubbo.demo.DemoService" ref=”demoService”/>
在上面的配置中,spring容器在啟動的過程中會解析自定義的schema元素dubbo並轉換成實際的配置實現ServiceBean ,並把服務暴露出去。
ServiceBean除了繼承dubbo自己的配置抽象類(ServiceConfig)以外,還實現了一系列的spring接口用來參與到spring容器的啟動以及bean的創建過程中去。由於spring實例化的ServiceBean是單例模式的,在Spring的容器ApplicationContext的啟動過程refresh過程中最后第二步會預先初始化單例的bean, 在bean的初始化過程會設置beanName, 設置容器applicationContext, 回調 InitializingBean的afterPropertiesSet。
最后一步finishRefresh會觸發ContextRefreshedEvent事件, 而ServiceBean實現了ApplicationListener接口監聽了此事件, 而在之前一步實例化的ServiceBean注冊了這個事件,所以ServiceBean的onApplicationEvent(ApplicationEvent event)方法被觸發, 在這個方法中觸發了export方法來暴露服務。
ServiceConfig.doExportUrls()執行具體的export過程
1. loadRegistries(true)
checkRegistry如果xml中沒有配置注冊中,從dubbo.properties中讀取配置,構建RegistryConfig對象並賦值
構建注冊中心URL統一數據模式集合List<registryUrl>
2. 因為dubbo支持多協議配置,遍歷所有協議分別根據不同的協議把服務export到不同的注冊中心上去
a) 判斷是否是泛型暴露
b) 根據協議構建暴露服務的統一數據模型URL
c) 配置的了monitor加載monitor,並給URL設置MONITOR_KEY
d) 給注冊中regitryUrl設置EXPORT_KEY值為前面構建的暴露服務url
e) 根據服務具體實現,實現接口以及regitryUrl從代理工廠ProxyFactory獲取代理Invoker(繼承於AbstractProxyInvoker),它是對具體實現的一種代理
f) Protocol.export(invoker) 暴露服務invoker
Invoker包含上一步傳入的RegistryUrl, registryUrl的protocol值為registry
ProtocolListenerWrapper和ProtocolFilterWrapper對於協議為REGISTRY_PROTOCOL直接跳過,最終由RegistryProtocol處理export的過程
RegistryProtocol暴露服務過程
這里傳入的Invoker是由RegistryUrl從ProxyFactory得到的Invoker
1. 從Invoker獲取providerUrl,在獲取cacheKey, 根據cacheKey獲取本地緩存的ExporterChangeableWrapper(exporter代理,建立返回的exporter與protocol export出的exporter的對應關系), 如果存在返回。
2. 如果不存在,根據傳入的 Invoker獲取providerUrl, 在構建InvokerDelegete(originInvoker, providerUrl)
3. Protocol.exprot(invokerDelegete) 根據providerUrl 的協議(一般是dubbo協議)通過Protocol的設配類暴露服務,得到exporter
4. 利用providerUr導出的exporter和invoker構建對象ExporterChangeableWrapper緩存到本地
5. 由Invoker得到registryUrl。
在根據registryUrl從RegistryFactory獲取Registry, 獲取RegistryUrl的注冊中心協議,這里我們拿zooKeeper協議為例。由dubbo的擴展機制得到的是ZookeeperRegistryFactory,得到注冊器為ZookeeperRegistry
6. 由Invoker獲取ProviderUrl在去除不需要在注冊中心看到的字段得到registryProviderUrl
7. 注冊中心(ZookeeperRegistry)注冊registryProviderUrl
Registry.register(registryProviderUrl)
8. 由registryProviderUrl獲取overrideSubscribeUrl,在構建OverrideListener
9. registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener) 注冊中心訂閱這個url, 用來當數據變化通知重新暴露, 哪zookeeper為例,暴露服務會在zookeeper生成一個節點,當節點發生變化的時候會觸發overrideSubscribeListener的notify方法重新暴露服務
10. 構建並返回一個新的exporter實例
DubboProtocol暴露服務的過程
1. 從invoker獲取統一數據模型url
2. 由url構建serviceKey(一般由端口,接口名,版本,group分組)
如:com.alibaba.dubbo.demo.DemoService:20880 這個是由接口和端口組成的
3. 構建DubboExporter放入本地map做緩存
4. 根據url openserver。 查找本地緩存以key為url.getAddress如果沒有ExchangeServer創建。設置heartbeat時間,設置編碼解碼協議
根據url和ExchangeHandler 綁定server並返回(具體如何綁定專題介紹)
5. 返回DubboExporter對象
官方文檔服務發布序列圖
發布活動圖