# 注冊中心
dubbo中可以使用的注冊中心有:MulticastRegistry、RedisRegistry、ZookeeperRegistry,分別是組播注冊中心、redis保存數據的注冊中心以及zookeeper保存數據的注冊中心;
在實現上,注冊中心實現了Registry接口
```
URL getUrl();
boolean isAvailable();
void destroy();
void register(URL url); // 注冊服務
void unregister(URL url); // 取消注冊
void subscribe(URL url, NotifyListener listener); // 訂閱符合條件的已注冊數據,當有注冊數據變更時自動推送
void unsubscribe(URL url, NotifyListener listener); // 取消訂閱
List<URL> lookup(URL url); // 查詢符合條件的已注冊數據,與訂閱的推模式相對應,這里為拉模式,只返回一次結果。
```
AbstractRegistry是一個抽象類,實現了Registry接口,內部時注冊中心的基本功能,有幾個主要屬性
```
private final Set<URL> registered = new ConcurrentHashSet<URL>();// 保存注冊的服務
private final ConcurrentMap<URL, Set<NotifyListener>> subscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();// 保存訂閱url的通知事件
private final ConcurrentMap<URL, Map<String, List<URL>>> notified = new ConcurrentHashMap<URL, Map<String, List<URL>>>();// 保存通知的url列表
private URL registryUrl; // 注冊中心的url
```
AbstractRegistry實現接口的邏輯如下:
```
public void register(URL url) // 將url保存到registered集合中
public void unregister(URL url) // 從registered集合中移除url
public void subscribe(URL url, NotifyListener listener) // 訂閱服務時將 url和監聽事件保存到subscribed變量中,一個url有多個監聽事件
public void unsubscribe(URL url, NotifyListener listener) // 取消訂閱,移除subscribed中的監聽事件
```
FailbackRegistry也是一個抽象類,繼承了AbstractRegistry類,主要用來失敗重試。
## 發布服務
1. RegistryProtocol發布服務時,會首先創建Registry注冊中心或獲取已經初始化的注冊中心
2.
## 引用服務
1. RegistryProtocol發布服務時,會首先創建Registry注冊中心或獲取已經初始化的注冊中心
2. 從引用的服務獲取url,使用注冊中心的register注冊`consumer://xxx/xxx?xxx`,在zookeeper上創建`/dubbo/接口名/consumers/consumer://xxx`節點。
3. 之后,使用注冊中心subscribe方法訂閱服務消費者`consumer://xxx/xxx?xxx`,根據url中category的值創建以下幾個節點,并添加監聽事件
```
[/dubbo/com.alibaba.dubbo.demo.DemoService/providers,
/dubbo/com.alibaba.dubbo.demo.DemoService/configurators,
/dubbo/com.alibaba.dubbo.demo.DemoService/routers]
```
```
-| MockClusterInvoker
-|FailoverClusterInvoker
—| Directory 返回一個Invoker列表
```
```
RegistryDirectory的notify中會
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);
protocol是DubboProtocol,refer時會創建client
client = Exchangers.connect(url, requestHandler);
Exchangers.connect(url, requestHandler);
HeaderExchanger connect()
Transporters connect()
NettyTransporter connect()
```
```
cluster.join(directory);
|- MockClusterInvoker
|— FailoverClusterInvoker
|- RegistryDirectory
directory.list(invocation);會返回Invoker列表,然后根據調用
```