Dubbo系列之 (二)Registry註冊中心-註冊(1)
阿新 • • 發佈:2020-08-09
# 引導
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