標籤:dubbo
首先DUBBO本質上是一款RPC架構,不可缺少的2個角色:服務提供者和服務消費者。
已經剖析了服務端暴露連接埠過程。本文簡單說下註冊中心。
1.註冊中心是什麼玩意
這是官網提供的圖例
650) this.width=650;" src="http://s2.51cto.com/wyfs02/M00/8B/F7/wKioL1hd64ujeWFHAAHY0C6Ailg777.png" title="1.png" alt="wKioL1hd64ujeWFHAAHY0C6Ailg777.png" />
通過圖例,可以看出消費者和提供者並不是直接通訊的,中間有個第三者,就是註冊中心。這種結構,可以實現消費者和提供者兩者的依賴,和參數資訊的叢集化。所以這帶來了幾個問題。
-
服務註冊
-
服務發現
-
服務訂閱
-
服務通知
2. 服務暴露及服務註冊過程
《Dubbo點滴(4)之暴露服務解析》已經剖析了dubbo協議具體開啟網路連接埠過程。本節內容會隱去這部分內容。因為一個完整的服務暴露,主要涉及2部分內容,1)開啟連接埠等待消費者串連;2)將服務資訊登記到註冊中心,以告知消費者可以串連了。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/8B/FA/wKiom1hd7nHhegDoAADMiy-mF8w911.png" title="2.png" alt="wKiom1hd7nHhegDoAADMiy-mF8w911.png" />
有3點需要說明:
1)首先,根據條件判斷會暴露一個injvm本地服務(step 6);
InjvmProtocol協議完成,主要供同一JVM種的消費者調用,提供RPC效率。
2) 為服務暴露一個dubbo服務(step 12),一般為DubboProtocol完成
3)step 12提供的的服務,註冊到註冊中心(step 13-step 23)。這一步是本文的剖析重點。
3.認識註冊中心
650) this.width=650;" src="http://www.myexception.cn/img/2014/08/01/110353770.jpg" width="854" height="635" alt="110353770.jpg" />
該圖是DUBBO的總體結構圖。重點停留在Resistry層。比較重要的是幾個組件
ZookeeperRegistry :負責與zookeeper進行互動
RegistryProtocol :從註冊中心擷取可用服務,或者將服務註冊到zookeeper,然後提供服務或者提供調用代理。
RegistryDirectory :維護著所有可用的遠程Invoker或者本地的Invoker。這個類實現了NotifyListner。
NotifyListener :負責RegistryDirectory和ZookeeperRegistry的通訊。
FailbackRegistry:繼承自Registry,實現了失敗重試機制。
4. 註冊中心資料模型
650) this.width=650;" src="http://s5.51cto.com/wyfs02/M01/8B/F7/wKioL1hd9GbhoQpFAAB6Ku26nf4144.jpg" title="55.jpg" alt="wKioL1hd9GbhoQpFAAB6Ku26nf4144.jpg" />
流程說明:
-
服務提供者啟動時
-
服務消費者啟動時
-
監控中心啟動時
4.Registry 結構樹
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/8B/F7/wKioL1hd9eThQ4lUAABw_9KRcyI681.png" title="6.png" alt="wKioL1hd9eThQ4lUAABw_9KRcyI681.png" />
ZookeeperRegistry是常見的註冊中心實現方案,由ZookeeperRegistryFactory負責構造。
AbstractRegistry這個類主要儲存的是已經註冊的服務介面,已經訂閱的服務介面和已經收到通知的介面的URL,不能直接調用。
public abstract class AbstractRegistry implements Registry { // 本地磁碟緩衝,其中特殊的key值.registies記錄註冊中心列表,其它均為notified服務提供者列表 private final Properties properties = new Properties(); // 檔案快取定時寫入 private final ExecutorService registryCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveRegistryCache", true)); //是否是同步儲存檔案 private final boolean syncSaveFile ; private final AtomicLong lastCacheChanged = new AtomicLong(); private final Set<URL> registered = new ConcurrentHashSet<URL>(); private final ConcurrentMap<URL, Set<NotifyListener>> subscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>(); private final ConcurrentMap<URL, Map<String, List<URL>>> notified = new ConcurrentHashMap<URL, Map<String, List<URL>>>(); ... }
FailbackRegistry 繼承自AbstractRegistry ,實現了失敗重試機制。
public abstract class FailbackRegistry extends AbstractRegistry {// 定時任務執行器private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboRegistryFailedRetryTimer", true));// 失敗重試定時器,定時檢查是否有請求失敗,如有,無限次重試private final ScheduledFuture<?> retryFuture;private final Set<URL> failedRegistered = new ConcurrentHashSet<URL>();private final Set<URL> failedUnregistered = new ConcurrentHashSet<URL>();private final ConcurrentMap<URL, Set<NotifyListener>> failedSubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();private final ConcurrentMap<URL, Set<NotifyListener>> failedUnsubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();private final ConcurrentMap<URL, Map<NotifyListener, List<URL>>> failedNotified = new ConcurrentHashMap<URL, Map<NotifyListener, List<URL>>>();...}
5.服務提供者啟動的註冊過程
服務提供者啟動時 向/dubbo/com.foo.BarService/providers目錄下寫入自己的URL地址。接下來,找尋下代碼執行路徑。RegistryProtocol 作為註冊中心的核心組件,作為代碼的入口,還要明確一點,這是個註冊登記過程。
//入口public class RegistryProtocol implements Protocol {final Registry registry = getRegistry(originInvoker);final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);registry.register(registedProviderUrl);}public abstract class AbstractRegistry implements Registry { public void register(URL url) { if (url == null) { throw new IllegalArgumentException("register url == null"); } if (logger.isInfoEnabled()){ logger.info("Register: " + url); } registered.add(url); }...}public abstract class FailbackRegistry extends AbstractRegistry {public void register(URL url) { super.register(url); failedRegistered.remove(url); failedUnregistered.remove(url); try { // 向伺服器端發送註冊請求 doRegister(url); } catch (Exception e) { ... } // 將失敗的註冊請求記錄到失敗列表,定時重試 failedRegistered.add(url); } protected abstract void doRegister(URL url); protected abstract void doUnregister(URL url); protected abstract void doSubscribe(URL url, NotifyListener listener); protected abstract void doUnsubscribe(URL url, NotifyListener listener);...} public class ZookeeperRegistry extends FailbackRegistry { public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) { super(url); //如果provider的url是“0.0.0.0”或者在參數中帶anyHost=true則拋出異常登入位址不存在 if (url.isAnyHost()) { throw new IllegalStateException("registry address == null"); } //服務分組(預設“dubbo”) String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT); if (! group.startsWith(Constants.PATH_SEPARATOR)) { group = Constants.PATH_SEPARATOR + group; } //服務分組根地址 this.root = group; zkClient = zookeeperTransporter.connect(url); //添加狀態監聽器 zkClient.addStateListener(new StateListener() { public void stateChanged(int state) { if (state == RECONNECTED) { try { recover(); } catch (Exception e) { logger.error(e.getMessage(), e); } } } }); } protected void doRegister(URL url) { try { //串連註冊中心註冊,在zk上建立節點 zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true)); } catch (Throwable e) { throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); } } }
6. 註冊中心關係類圖
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M01/8B/FB/wKiom1hd--Pyk5anAADYmQZPcMI910.png" title="22.png" alt="wKiom1hd--Pyk5anAADYmQZPcMI910.png" />
重要概念:
ZookeeperRegistry :負責與zookeeper進行互動
RegistryProtocol :從註冊中心擷取可用服務,或者將服務註冊到zookeeper,然後提供服務或者提供調用代理。
RegistryDirectory :維護著所有可用的遠程Invoker或者本地的Invoker。這個類實現了NotifyListner。
NotifyListener :負責RegistryDirectory和ZookeeperRegistry的通訊。
FailbackRegistry:繼承自Registry,實現了失敗重試機制。
本文出自 “簡單” 部落格,請務必保留此出處http://dba10g.blog.51cto.com/764602/1885719
Dubbo點滴(5)之服務註冊中心