天天看點

Dubbo服務提供者Provider啟動流程下(四)

服務暴露實際上就是啟動server本地監聽,并且将服務資訊注冊到注冊中心上。在dubbo:service上的export可以指定是否暴露,同時provider也可以指定延遲暴露的時間。

ServiceConfig#doExport -> ServiceConfig#doExportUrls

serviceConfig#doExportUrlsFor1Protocol

這個方法主要就是将服務的配置資訊包裝成一個url,并且本地啟動服務,并将服務資訊釋出到注冊中心。代碼貼出來會比較多,我這邊按重點貼出部分

代碼前端包括了用Map存儲該協定的所有配置參數,包括協定名稱、dubbo版本、目前系統時間戳、程序ID、application配置、module配置、預設服務提供者參數(ProviderConfig)、協定配置、服務提供Dubbo:service的屬性。

将service 裡面的 method 裡面的 argument 也加到 map中,其中就包括了callback。

然後泛化資訊添加。另外将所有的方法名也添加進map,以逗号分隔,這邊使用javassiat位元組碼生成器擷取所有的方法具體詳解代碼   String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();

之後有token的處理,還有擷取服務的host和port

然後再一次封裝服務的暴露URL 

URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);

大體内容如下:

接着擷取 動态配置中心,并将url寫到配置中心。接着往下

根據scope來暴露服務,如果scope不配置,則預設本地與遠端都會暴露,如果配置成local或remote,那就隻能是二選一。

如果scope不為remote,則先在本地暴露(injvm):,具體暴露服務的具體實作,将在remote 模式中詳細分析。

如果scope不為local,則将服務暴露在遠端。

remote方式,檢測目前配置的所有注冊中心,如果注冊中心不為空,則周遊注冊中心,将服務依次在不同的注冊中心進行注冊。

如果dubbo:service的dynamic屬性未配置, 嘗試取dubbo:registry的dynamic屬性,該屬性的作用是否啟用動态注冊,如果設定為false,服務注冊後,其狀态顯示為disable,需要人工啟用,當服務不可用時,也不會自動移除,同樣需要人工處理,此屬性不要在生産環境上配置。

根據注冊中心url(注冊中心url),建構監控中心的URL,如果監控中心URL不為空,則在服務提供者URL上追加monitor,其值為監控中心url(已編碼)。

下面就是服務暴露的細節了

我們debug到invoke這邊,對與invoke  後續會出專門的章節來介紹。這邊隻要了解到Invoke中的URL

registryURL = registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=33205&registry=zookeeper&timestamp=1639897064350

invoke.url =    registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.0.102%3A20880%2Forg.apache.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo-api-provider%26bind.ip%3D192.168.0.102%26bind.port%3D20880%26default.deprecated%3Dfalse%26default.dynamic%3Dfalse%26default.register%3Dtrue%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dfalse%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.demo.DemoService%26methods%3DsayHello%26pid%3D33205%26register%3Dtrue%26release%3D%26side%3Dprovider%26timestamp%3D1639897069365&pid=33205&registry=zookeeper&timestamp=1639897064350  其中協定就是register

在dubbo的擴充中,對于擴充點接口的方法上有@Adaptive注解的話,會去參數裡面擷取URL,然後取對應的key,這邊的key就是register。那麼很好了解下面的方法了Exporter<?> exporter = protocol.export(wrapperInvoker);

實際上調用的RegistryProtocol的exporter。

在上面的URL providerUrl = getProviderUrl(originInvoker);方法中,把invoke中的url擷取後,替換了前面的register協定,變成了dubbo協定,即dubbo://開頭的URL。

接下來看下面的執行doLocalExport方法

注意這裡面使用了一個invoke的委托類,将url改成了providerUrl,即dubbo協定開頭。是以根據dubbo的擴充實作,拿到了protocal實作類就是DubboProtocal。

DubboProtocal#export

DubboProtocal#openServer

同一個主機上上不同服務,使用同一個address,是以共享一個ExchangeServer,如果記憶體中找不到,則create

為服務提供者url增加channel.readonly.sent屬性,預設為true,表示在發送請求時,是否等待将位元組寫入socket後再傳回,預設為true。

為服務提供者url增加heartbeat屬性,表示心跳間隔時間,預設為60*1000,表示60s。

為服務提供者url增加server屬性,可選值為netty,mina等等,預設為netty。

根據SPI機制,判斷server屬性是否支援。

為服務提供者url增加codec屬性,預設值為dubbo,協定編碼方式。

根據服務提供者URI,服務提供者指令請求處理器requestHandler建構ExchangeServer執行個體。requestHandler的實作具體在以後詳細分析Dubbo服務調用時再詳細分析。

驗證用戶端類型是否可用。

在上文的RegisterProtocal#export -> RegisterProtocal#getRegistry

 根據注冊中心URL,從注冊中心工廠中擷取指定的注冊中心實作類:zookeeper注冊中心的實作類為:ZookeeperRegistry

這裡面registryFactory的實作類是啥呢?這個就在之前章節講到了擴充點的IOC注入,實際上registryFactory也是有ExtensionLoader去加載的。

擷取服務提供者URL中的register屬性,如果為true,則調用注冊中心的ZookeeperRegistry#register方法向注冊中心注冊服務(實際由其父類FailbackRegistry實作,ZookeeperRegistry extends FailbackRegistry)。

FailbackRegistry#register -> ZookeeperRegistry#doRegister

最後服務提供者向注冊中心訂閱自己,主要是為了服務提供者URL發送變化後重新暴露服務,當然,會将dubbo:reference的check屬性設定為false。

繼續閱讀