1. 程式人生 > >Dubbo系列之 (二)Registry註冊中心-註冊(1)

Dubbo系列之 (二)Registry註冊中心-註冊(1)

# 引導 dubbo的服務的註冊與發現,需要通過第三方註冊中心來協助完成,目前dubbo支援的註冊中心包括 zookeeper,consul,etcd3,eureka,nacas,redis,sofa。這些註冊中心的不同支援在之後的篇章進行分享。 # 基礎鋪墊 在鋪墊一些基礎內容之前,根據如果下幾個問題來進行回答,或許能更好的闡明dubbo的實現服務的註冊和發現的實現過程。 1、dubbo是在什麼時機與註冊中心建立連線。 2、dubbo服務註冊和匯出的時機在什麼時候。 3、dubbo服務的訂閱時機是在什麼時候。 4、dubbo服務的上下線是如何通知訂閱者的。 5、dubbo是如何把這些各種第三方註冊中心進行整合的。 為了回答上面的五個問題,我們一起去從dubbo的原始碼探尋答案,這些問題和服務的註冊有關,那麼首先我們需要的就是去dubbo-registry這個原始碼模組去查詢。 ## 基礎資料結構 ###1、dubbo 還是通過SPI技術,根據引數URL來動態選擇不同的註冊中心。 ``` @SPI("dubbo") public interface RegistryFactory { @Adaptive({"protocol"}) Registry getRegistry(URL url); } ``` RegistryFactory 就是產生一個註冊中心的工程,它有個自適應的方法getRegistry,那麼我們知道dubbo會通過javassist動態產生一個RegistryFactory$Adaptive類,並且getRegistry方法的內部實現大致是如下: ``` public class RegistryFactory$Adaptive implements RegistryFactory { @Override public Registry getRegistry(URL url) { if (url == null) throw new IllegalArgumentException("url == null"); String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol()); if (extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.registry.RegistryFactory) " + "name from url (" + url.toString() + ") use keys([protocol])"); RegistryFactory extension = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension(extName); return extension.getRegistry(url); } } ``` 它通過傳入的URL的protocol協議欄位排判斷是什麼型別註冊中心。例如,url的protocol的協議是zookeeper,那麼就會根據SPI的ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension("zookeeper")得到一個產生ZooKeeper註冊中心的工廠,也就是ZookeeperRegistryFactory,而ZookeeperRegistryFactory這個類的getRegistry就是返回一個Zookeeper註冊中心。 ###2、Registry 介面是所有註冊中心的抽象。它的類關係圖如下: ![](https://img2020.cnblogs.com/blog/672564/202008/672564-20200809120213006-1420869765.jpg) 可以看出其語義,一個註冊中心Registry是一個節點(extends Node),並且它具有註冊服務(extends RegistryService)的功能。 dubbo支援如下這些註冊中心zookeeper,consul,etcd3,eureka,nacas,redis,sofa,那麼就會產生相應如下的Registry: ZookeeperRegistry,ConsulRegistry,EtcdRegistry,NacosRegistry,RedisRegistry,SofaRegistry。類圖如下: ![](https://img2020.cnblogs.com/blog/672564/202008/672564-20200809120249417-195522540.jpg) 所以我們知道,這些註冊中心都是繼承FailbackRegistry,這個FailbackRegistry其意思就是說,如果一個服務註冊到當前某個註冊中心註冊失敗後,可會在後臺產生一個daemon執行緒,定時的把註冊失敗服務重新註冊,並且有一定的重試限制。 在上面的類圖中我們並沒有發現有個名為EurekaRegistry這樣的類,因為實現了另一個介面ServiceDiscovery方式,類名為EurekaServiceDiscovery來進行服務發現。這些不同的註冊中心的實現方式,會在下一個章節去討論它。 ### 3、RegistryProtocol dubbo的協議是通過名為org.apache.dubbo.rpc.Protocol來進行抽象的,那麼註冊協議也是一樣的,是通過org.apache.dubbo.registry.integration.RegistryProtocol來表達的,繼承org.apache.dubbo.rpc.Protocol。RegistryPrtocol是擴充套件點Protocol的具體實現,在[Dubbo系列之 (一)SPI擴充套件](https://www.cnblogs.com/liferecord/p/13445631.html)文章中提到,會一次呼叫其setter方法來注入其需要的屬性,RegistryPrtocol其中有個屬性就是RegistryFactory,那麼就要為它注入一個具體的RegistryFactory,那麼這個具體的RegistryFactory工廠是什麼型別,答案就是上面的RegistryFactory$Adaptive。為什麼?因為在[Dubbo系列之 (一)SPI擴充套件](https://www.cnblogs.com/liferecord/p/13445631.html)中提到了注入的屬性物件會從SpringExtensionFactory和SpiExtensionFactory工廠中查詢,剛好RegistryFactory也是一個擴充套件點,所以會在SpiExtensionFactory找出,並且SpiExtensionFactory工廠的實現如下: ``` public class SpiExtensionFactory implements ExtensionFactory { @Override public