Dubbo中Directory解析

Directory代表多個(gè)Invoker,可以把它看成List<Invoker>,但與List不同的是,它的值可能是動(dòng)態(tài)變化的,比如注冊(cè)中心推送變更。Cluster將Directory中的多個(gè)Invoker偽裝成一個(gè)Invoker,對(duì)上層透明,偽裝過(guò)程包含了容錯(cuò)邏輯,調(diào)用失敗后,重試另一個(gè)。

上面是文檔上對(duì)Directory的解釋。

Directory接口

Directory接口繼承了Node接口:

public interface Directory<T> extends Node {
    //獲取服務(wù)類(lèi)型
    Class<T> getInterface();

    //invoker列表,服務(wù)的列表
    List<Invoker<T>> list(Invocation invocation) throws RpcException;
}

AbstractDirectory

默認(rèn)實(shí)現(xiàn)為AbstractDirectory:

public abstract class AbstractDirectory<T> implements Directory<T> {

    // 日志輸出
    private static final Logger logger = LoggerFactory.getLogger(AbstractDirectory.class);
    //服務(wù)url
    private final URL url ;
    private volatile boolean destroyed = false;
    //消費(fèi)者url
    private volatile URL consumerUrl ;
    //路由
    private volatile List<Router> routers;
    
    public AbstractDirectory(URL url) {
        this(url, null);
    }
    
    public AbstractDirectory(URL url, List<Router> routers) {
        this(url, url, routers);
    }
    
    public AbstractDirectory(URL url, URL consumerUrl, List<Router> routers) {
        if (url == null)
            throw new IllegalArgumentException("url == null");
        this.url = url;
        this.consumerUrl = consumerUrl;
        setRouters(routers);
    }
    //對(duì)list方法的默認(rèn)實(shí)現(xiàn)
    public List<Invoker<T>> list(Invocation invocation) throws RpcException {
        if (destroyed){
            throw new RpcException("Directory already destroyed .url: "+ getUrl());
        }
        //獲取Invoker列表的具體實(shí)現(xiàn)由具體子類(lèi)實(shí)現(xiàn)
        List<Invoker<T>> invokers = doList(invocation);
        //路由
        List<Router> localRouters = this.routers; // local reference
        if (localRouters != null && localRouters.size() > 0) {
            for (Router router: localRouters){
                try {
                    if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, true)) {
                        //路由
                        invokers = router.route(invokers, getConsumerUrl(), invocation);
                    }
                } catch (Throwable t) {
                    logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
                }
            }
        }
        return invokers;
    }
    
    public URL getUrl() {
        return url;
    }
    
    public List<Router> getRouters(){
        return routers;
    }

    public URL getConsumerUrl() {
        return consumerUrl;
    }

    public void setConsumerUrl(URL consumerUrl) {
        this.consumerUrl = consumerUrl;
    }
    //構(gòu)造中調(diào)用的設(shè)置路由的方法
    protected void setRouters(List<Router> routers){
        // copy list
        routers = routers == null ? new  ArrayList<Router>() : new ArrayList<Router>(routers);
        // append url router
        String routerkey = url.getParameter(Constants.ROUTER_KEY);
        //指定了router,就使用制定的router來(lái)獲取擴(kuò)展實(shí)現(xiàn)
        if (routerkey != null && routerkey.length() > 0) {
            RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(routerkey);
            routers.add(routerFactory.getRouter(url));
        }
        // append mock invoker selector
        routers.add(new MockInvokersSelector());
        Collections.sort(routers);
        this.routers = routers;
    }

    public boolean isDestroyed() {
        return destroyed;
    }

    public void destroy(){
        destroyed = true;
    }
    //子類(lèi)實(shí)現(xiàn)具體的獲取invoker列表
    protected abstract List<Invoker<T>> doList(Invocation invocation) throws RpcException ;

}

Directory具體的實(shí)現(xiàn)有兩個(gè)RegistryDirectory注冊(cè)目錄服務(wù)和StaticDirectory靜態(tài)目錄服務(wù)。

RegistryDirectory

RegistryDirectory實(shí)現(xiàn)了NotifyListener接口,因此他本身也是一個(gè)監(jiān)聽(tīng)器,可以在服務(wù)變更時(shí)接受通知,消費(fèi)方要調(diào)用遠(yuǎn)程服務(wù),會(huì)向注冊(cè)中心訂閱這個(gè)服務(wù)的所有的服務(wù)提供方,訂閱的時(shí)候會(huì)調(diào)用notify方法,進(jìn)行invoker實(shí)例的重新生成,也就是服務(wù)的重新引用。在服務(wù)提供方有變動(dòng)時(shí),也會(huì)調(diào)用notify方法,有關(guān)notify方法在Dubbo中訂閱和通知解析那篇文章中已經(jīng)解釋,不做重復(fù)。subscribe方法也不做重復(fù)解釋。

StaticDirectory

靜態(tài)目錄服務(wù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • dubbo暴露服務(wù)有兩種情況,一種是設(shè)置了延遲暴露(比如delay="5000"),另外一種是沒(méi)有設(shè)置延遲暴露或者...
    加大裝益達(dá)閱讀 21,413評(píng)論 5 36
  • 首先還是Spring碰到dubbo的標(biāo)簽之后,會(huì)使用parseCustomElement解析dubbo標(biāo)簽,使用的...
    加大裝益達(dá)閱讀 6,962評(píng)論 0 11
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,692評(píng)論 18 399
  • 半夏,沉寂了一冬的荷塘,鋪開(kāi)繽紛色彩。先是翠的綠,眼下又是粉的紅、乳般白,花骨朵婷婷裊裊探出腦袋,熱烈,精彩,隨時(shí)...
    圓圓2408閱讀 1,207評(píng)論 7 9

友情鏈接更多精彩內(nèi)容