国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Dubbo服務(wù)提供者發(fā)布過(guò)程

lifesimple / 1792人閱讀

摘要:將標(biāo)記為服務(wù),使用對(duì)象來(lái)提供具體的服務(wù)。這整個(gè)過(guò)程算是該類的典型的執(zhí)行過(guò)程。從上面得知服務(wù)發(fā)布的第一二個(gè)過(guò)程獲取注冊(cè)中心信息和協(xié)議信息。對(duì)于端來(lái)說(shuō),上述服務(wù)發(fā)布的第步中要解決的問(wèn)題是根據(jù)指定協(xié)議向注冊(cè)中心注冊(cè)服務(wù)。

上圖是服務(wù)提供者暴露服務(wù)的主過(guò)程

首先ServiceConfig類拿到對(duì)外提供服務(wù)的實(shí)際類ref(如:HelloServiceImpl),然后通過(guò)ProxyFactory類的getInvoker方法使用ref生成一個(gè)AbstractProxyInvoker實(shí)例,到這一步就完成具體服務(wù)到Invoker的轉(zhuǎn)化。接下來(lái)就是Invoker轉(zhuǎn)換到Exporter的過(guò)程。

Dubbo處理服務(wù)暴露的關(guān)鍵就在Invoker轉(zhuǎn)換到Exporter的過(guò)程(如上圖中的紅色部分),Dubbo協(xié)議的Invoker轉(zhuǎn)為Exporter發(fā)生在DubboProtocol類的export方法,它主要是打開(kāi)socket偵聽(tīng)服務(wù),并接收客戶端發(fā)來(lái)的各種請(qǐng)求,通訊細(xì)節(jié)由Dubbo自己實(shí)現(xiàn).

服務(wù)發(fā)布過(guò)程大致分成3步

1、獲取注冊(cè)中心信息,構(gòu)建協(xié)議信息,然后將其組合。
2、通過(guò)ProxyFactory將HelloServiceImpl封裝成一個(gè)Invoker執(zhí)行 。
3、使用Protocol將invoker導(dǎo)出成一個(gè)Exporter(包括去注冊(cè)中心注冊(cè)服務(wù)等)。

這里面就涉及到幾個(gè)大的概念,ProxyFactory、Invoker、Protocol、Exporter

Export 服務(wù)暴露的步驟

1、首先會(huì)檢查各種配置信息 等標(biāo)簽的配置,填充各種屬性,總之就是保證我在開(kāi)始暴露服務(wù)之前,所有的東西都準(zhǔn)備好了,并且是正確的。
2、加載所有的注冊(cè)中心,因?yàn)槲覀儽┞斗?wù)需要注冊(cè)到注冊(cè)中心中去。
3、根據(jù)配置的所有協(xié)議和注冊(cè)中心url分別進(jìn)行導(dǎo)出。
4、進(jìn)行導(dǎo)出的時(shí)候,又是一波屬性的獲取設(shè)置檢查等操作。
5、如果配置的不是remote,則做本地導(dǎo)出。
6、如果配置的不是local,則暴露為遠(yuǎn)程服務(wù)。
7、不管是本地還是遠(yuǎn)程服務(wù)暴露,首先都會(huì)獲取Invoker。
8、獲取完Invoker之后,轉(zhuǎn)換成對(duì)外的Exporter,緩存起來(lái)。
9、執(zhí)行DubboProtocol類的export方法,打開(kāi)socket偵聽(tīng)服務(wù),并接收客戶端發(fā)來(lái)的各種請(qǐng)求。

概念介紹

先看一個(gè)簡(jiǎn)單的服務(wù)端例子,dubbo配置如下:





有一個(gè)服務(wù)接口HelloService,以及它對(duì)應(yīng)的實(shí)現(xiàn)類HelloServiceImpl。

將HelloService標(biāo)記為dubbo服務(wù),使用HelloServiceImpl對(duì)象來(lái)提供具體的服務(wù)。

使用zooKeeper作為注冊(cè)中心。

Invoker

Invoker,一個(gè)可執(zhí)行對(duì)象,能夠根據(jù)方法名稱、參數(shù)得到相應(yīng)的執(zhí)行結(jié)果。接口如下:

public interface Invoker {

    Class getInterface();

    URL getUrl();

    Result invoke(Invocation invocation) throws RpcException;

    void destroy();

}

而Invocation則包含了需要執(zhí)行的方法、參數(shù)等信息,接口如下:

public interface Invocation {

    URL getUrl();

    String getMethodName();

    Class[] getParameterTypes();

    Object[] getArguments();

}

目前其實(shí)現(xiàn)類只有一個(gè)RpcInvocation

Invoker這個(gè)可執(zhí)行對(duì)象的執(zhí)行過(guò)程分成三種類型:

本地執(zhí)行的Invoker

遠(yuǎn)程通信執(zhí)行的Invoker

多個(gè)類型2的Invoker聚合成的集群版Invoker

以HelloService接口為例:

本地執(zhí)行的Invokerserver端,含有對(duì)應(yīng)的HelloServiceImpl實(shí)現(xiàn),要執(zhí)行該接口方法,僅僅只需要通過(guò)反射執(zhí)行HelloServiceImpl對(duì)應(yīng)的方法即可。

遠(yuǎn)程通信執(zhí)行的Invokerclient端,要想執(zhí)行該接口方法,需要需要進(jìn)行遠(yuǎn)程通信,發(fā)送要執(zhí)行的參數(shù)信息給server端;server端,利用上述本地執(zhí)行的Invoker執(zhí)行相應(yīng)的方法,然后將返回的結(jié)果發(fā)送給client端。這整個(gè)過(guò)程算是該類Invoker的典型的執(zhí)行過(guò)程。

集群版的Invokerclient端,擁有某個(gè)服務(wù)的多個(gè)Invoker,此時(shí)client端需要做的就是將多個(gè)Invoker聚合成一個(gè)集群版的Invoker,client端使用的時(shí)候,僅僅通過(guò)集群版的Invoker來(lái)進(jìn)行操作。集群版的Invoker會(huì)從眾多的遠(yuǎn)程通信類型的Invoker中選擇一個(gè)來(lái)執(zhí)行(從中加入負(fù)載均衡、服務(wù)降級(jí)等策略),類似服務(wù)治理,dubbo已經(jīng)實(shí)現(xiàn)了、

看下Invoker的實(shí)現(xiàn)情況:

ProxyFactory

對(duì)于Server端,主要負(fù)責(zé)將服務(wù)如HelloServiceImpl統(tǒng)一進(jìn)行包裝成一個(gè)Invoker,通過(guò)反射來(lái)執(zhí)行具體的HelloServiceImpl對(duì)象的方法

接口定義如下:

@SPI("javassist")
public interface ProxyFactory {

     //針對(duì)client端,創(chuàng)建出代理對(duì)象
    @Adaptive({Constants.PROXY_KEY})
     T getProxy(Invoker invoker) throws RpcException;

    //針對(duì)server端,將服務(wù)對(duì)象如HelloServiceImpl包裝成一個(gè)Invoker對(duì)象
    @Adaptive({Constants.PROXY_KEY})
     Invoker getInvoker(T proxy, Class type, URL url) throws RpcException;

}

ProxyFactory的接口實(shí)現(xiàn)有JdkProxyFactory、JavassistProxyFactory,默認(rèn)是JavassistProxyFactory, JavassistProxyFactory內(nèi)容如下:

public class JavassistProxyFactory extends AbstractProxyFactory {

    @SuppressWarnings("unchecked")
    public  T getProxy(Invoker invoker, Class[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    public  Invoker getInvoker(T proxy, Class type, URL url) {
        // TODO Wrapper類不能正確處理帶$的類名
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf("$") < 0 ? proxy.getClass() : type);
        return new AbstractProxyInvoker(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName, 
                                      Class[] parameterTypes, 
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }

}

可以看到創(chuàng)建了一個(gè)AbstractProxyInvoker(這類就是本地執(zhí)行的Invoker),AbstractProxyInvoker對(duì)invoke()方法的實(shí)現(xiàn)如下:

public Result invoke(Invocation invocation) throws RpcException {
    try {
        return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
    } catch (InvocationTargetException e) {
        return new RpcResult(e.getTargetException());
    } catch (Throwable e) {
        throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}

綜上所述,服務(wù)發(fā)布的第二個(gè)過(guò)程就是:使用ProxyFactory將HelloServiceImpl封裝成一個(gè)本地執(zhí)行的Invoker。

Protocol

從上面得知服務(wù)發(fā)布的第一、二個(gè)過(guò)程:

1、獲取注冊(cè)中心信息dubbo:registry和協(xié)議信息dubbo:protocol。
2、使用ProxyFactory將HelloServiceImpl封裝成一個(gè)本地執(zhí)行的Invoker。

執(zhí)行這個(gè)服務(wù)->執(zhí)行這個(gè)本地的Invoker->調(diào)用AbstractProxyInvoker.invoke(Invocation invocation)方法,方法的執(zhí)行過(guò)程就是通過(guò)反射執(zhí)行HelloServiceImpl。

現(xiàn)在的問(wèn)題是:客戶端如何調(diào)用服務(wù)端的方法(服務(wù)注冊(cè)到注冊(cè)中心->客戶端向注冊(cè)中心訂閱服務(wù)->客戶端調(diào)用服務(wù)端的方法)和上述Invocation參數(shù)的來(lái)源問(wèn)題

對(duì)于Server端來(lái)說(shuō),上述服務(wù)發(fā)布的第3步中Protocol要解決的問(wèn)題是:

根據(jù)指定協(xié)議向注冊(cè)中心注冊(cè)HelloService服務(wù)。

當(dāng)客戶端根據(jù)協(xié)議調(diào)用這個(gè)服務(wù)時(shí),將客戶端傳遞過(guò)來(lái)的Invocation參數(shù)交給上述的Invoker來(lái)執(zhí)行。

所以Protocol會(huì)加入遠(yuǎn)程通信這塊,根據(jù)客戶端的請(qǐng)求來(lái)獲取參數(shù)Invocation。

先來(lái)看下Protocol接口的定義:

@SPI("dubbo")
public interface Protocol {

    int getDefaultPort();

    //針對(duì)server端來(lái)說(shuō),將本地執(zhí)行類的Invoker通過(guò)協(xié)議暴漏給外部。這樣外部就可以通過(guò)協(xié)議發(fā)送執(zhí)行參數(shù)Invocation,然后交給本地Invoker來(lái)執(zhí)行
    @Adaptive
     Exporter export(Invoker invoker) throws RpcException;

    //這個(gè)是針對(duì)客戶端的,客戶端從注冊(cè)中心獲取服務(wù)器端發(fā)布的服務(wù)信息
    //通過(guò)服務(wù)信息得知服務(wù)器端使用的協(xié)議,然后客戶端仍然使用該協(xié)議構(gòu)造一個(gè)Invoker。這個(gè)Invoker是遠(yuǎn)程通信類的Invoker。
    //執(zhí)行時(shí),需要將執(zhí)行信息通過(guò)指定協(xié)議發(fā)送給服務(wù)器端,服務(wù)器端接收到參數(shù)Invocation,然后交給服務(wù)器端的本地Invoker來(lái)執(zhí)行
    @Adaptive
     Invoker refer(Class type, URL url) throws RpcException;

    void destroy();

}

我們?cè)賮?lái)詳細(xì)看看服務(wù)發(fā)布的第3步(ServiceConfig):

Exporter exporter = protocol.export(invoker);

protocol的來(lái)歷是:

Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException{
    if (arg0 == null) {
        throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null"); 
    }
    if (arg0.getUrl() == null) {
        throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
    }
    com.alibaba.dubbo.common.URL url = arg0.getUrl();
    String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
    if(extName == null) {
        throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])"); 
    }
    com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)com.alibaba.dubbo.common.ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
    return extension.export(arg0);
}

public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0,com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException{
    if (arg1 == null) { 
        throw new IllegalArgumentException("url == null"); 
    }
    com.alibaba.dubbo.common.URL url = arg1;
    String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
    if(extName == null) {
        throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])"); 
    }
    com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)com.alibaba.dubbo.common.ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
    return extension.refer(arg0, arg1);
}

export(Invoker invoker)的過(guò)程即根據(jù)Invoker中url的信息來(lái)最終選擇Protocol的實(shí)現(xiàn),默認(rèn)實(shí)現(xiàn)是DubboProtocol,然后再對(duì)DubboProtocol進(jìn)行依賴注入,進(jìn)行wrap包裝(getExtension()方法)。

Protocol的實(shí)現(xiàn)情況:

可以看到在返回DubboProtocol之前,經(jīng)過(guò)了ProtocolFilterWrapper、ProtocolListenerWrapper、RegistryProtocol的包裝

所謂包裝就是如下內(nèi)容:

package com.alibaba.xxx;

import com.alibaba.dubbo.rpc.Protocol;

public class XxxProtocolWrapper implemenets Protocol {
    Protocol impl;

    public XxxProtocol(Protocol protocol) { impl = protocol; }

    // 接口方法做一個(gè)操作后,再調(diào)用extension的方法
    public Exporter export(final Invoker invoker) {
        //... 一些操作
        impl .export(invoker);
        // ... 一些操作
    }

    // ...
}

使用裝飾器模式,類似AOP的功能

下面主要講解RegistryProtocol和DubboProtocol,先暫時(shí)忽略ProtocolFilterWrapper、ProtocolListenerWrapper

RegistryProtocol.export() 主要功能是將服務(wù)注冊(cè)到注冊(cè)中心

DubboProtocol.export() 服務(wù)導(dǎo)出功能:

創(chuàng)建一個(gè)DubboExporter,封裝Invoker。

根據(jù)Invoker的url獲取ExchangeServer通信對(duì)象(負(fù)責(zé)與客戶端的通信模塊)。

現(xiàn)在我們搞清楚我們的目的,通過(guò)通信對(duì)象獲取客戶端傳來(lái)的Invocation參數(shù),然后找到對(duì)應(yīng)的DubboExporter(即能夠獲取到本地Invoker)就可以執(zhí)行服務(wù)了。

在DubboProtocol中,每個(gè)ExchangeServer通信對(duì)象都綁定了一個(gè)ExchangeHandler對(duì)象,內(nèi)容如下:

private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {

    public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
        if (message instanceof Invocation) {
            Invocation inv = (Invocation) message;
            Invoker invoker = getInvoker(channel, inv);
            RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
            ......
            return invoker.invoke(inv);
        }
        throw new RemotingException(channel, "Unsupported request: " + message == null ? null : (message.getClass().getName() + ": " + message) + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress());
    }
};

可以看到該類才是真正與客戶端通信,在獲取到Invocation參數(shù)后,調(diào)用getInvoker()來(lái)獲取本地的Invoker(先從exporterMap中獲取Exporter),就可以調(diào)用服務(wù)了。

而對(duì)于通信這塊,接下來(lái)會(huì)專門來(lái)詳細(xì)的說(shuō)明,從reply參數(shù)可知,重點(diǎn)在了解ExchangeChannel

Exporter

負(fù)責(zé)維護(hù)invoker的生命周期,包含一個(gè)Invoker對(duì)象,接口定義如下:

public interface Exporter {

    Invoker getInvoker();

    void unexport();

}
結(jié)束語(yǔ)

以上就是本文簡(jiǎn)略地介紹了及服務(wù)發(fā)布過(guò)程中的幾個(gè) ProxyFactory、Invoker、Protocol、Exporter 概念

參考:http://dubbo.apache.org/books/dubbo-dev-book/implementation.html
參考:https://blog.csdn.net/qq418517226/article/details/51818769

Contact

作者:鵬磊

出處:http://www.ymq.io/2018/06/13/dubbo_rpc_export

版權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)注明出處

Wechat:關(guān)注公眾號(hào),搜云庫(kù),專注于開(kāi)發(fā)技術(shù)的研究與知識(shí)分享

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71184.html

相關(guān)文章

  • Dubbo 一篇文章就夠了:從入門到實(shí)戰(zhàn)

    摘要:?jiǎn)?dòng)容器,加載,運(yùn)行服務(wù)提供者。服務(wù)提供者在啟動(dòng)時(shí),在注冊(cè)中心發(fā)布注冊(cè)自己提供的服務(wù)。注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者。 一 為什么需要 dubbo 很多時(shí)候,其實(shí)我們使用這個(gè)技術(shù)的時(shí)候,可能都是因?yàn)轫?xiàng)目需要,所以,我們就用了,但是,至于為什么我們需要用到這個(gè)技術(shù),可能自身并不是很了解的,但是,其實(shí)了解技術(shù)的來(lái)由及背景知識(shí),對(duì)...

    tomener 評(píng)論0 收藏0
  • Dubbo服務(wù)暴露過(guò)程

    摘要:根據(jù)的值,進(jìn)行服務(wù)暴露。如果配置為則不暴露,如果服務(wù)未配置成,則本地暴露如果未配置成,則暴露遠(yuǎn)程服務(wù)。提供者向注冊(cè)中心訂閱所有注冊(cè)服務(wù)當(dāng)注冊(cè)中心有此服務(wù)的覆蓋配置注冊(cè)進(jìn)來(lái)時(shí),推送消息給提供者,重新暴露服務(wù),這由管理頁(yè)面完成。 概覽 dubbo暴露服務(wù)有兩種情況,一種是設(shè)置了延遲暴露(比如delay=5000),另外一種是沒(méi)有設(shè)置延遲暴露或者延遲設(shè)置為-1(delay=-1): 設(shè)置了...

    bigdevil_s 評(píng)論0 收藏0
  • Dubbo 2.7.1 踩坑記

    摘要:面試題服務(wù)提供者能實(shí)現(xiàn)失效踢出是什么原理高頻題服務(wù)宕機(jī)的時(shí)候,該節(jié)點(diǎn)由于是持久節(jié)點(diǎn)會(huì)永遠(yuǎn)存在,而且當(dāng)服務(wù)再次重啟的時(shí)候會(huì)將重新注冊(cè)一個(gè)新節(jié)點(diǎn)。 Dubbo 2.7 版本增加新特性,新系統(tǒng)開(kāi)始使用 Dubbo 2.7.1 嘗鮮新功能。使用過(guò)程中不慎踩到這個(gè)版本的 Bug。 系統(tǒng)架構(gòu) Spring Boot 2.14-Release + Dubbo 2.7.1 現(xiàn)象 Dubbo 服務(wù)者啟動(dòng)...

    wudengzan 評(píng)論0 收藏0
  • 網(wǎng)關(guān)實(shí)現(xiàn)灰度發(fā)布

    摘要:就是一種灰度發(fā)布方式,讓一部分用戶繼續(xù)用,一部分用戶開(kāi)始用,如果用戶對(duì)沒(méi)有什么反對(duì)意見(jiàn),那么逐步擴(kuò)大范圍,把所有用戶都遷移到上面來(lái)。灰度發(fā)布可以保證整體系統(tǒng)的穩(wěn)定,在初始灰度的時(shí)候就可以發(fā)現(xiàn)調(diào)整問(wèn)題,以保證其影響度。 一、背景互聯(lián)網(wǎng)產(chǎn)品開(kāi)發(fā)有個(gè)非常特別的地方,就是不停的升級(jí),升級(jí),再升級(jí)。采用敏捷開(kāi)發(fā)的方式,基本上保持每周或者每?jī)芍芤淮蔚陌l(fā)布頻率,系統(tǒng)升級(jí)總是伴隨著各種風(fēng)險(xiǎn),新舊版本兼...

    stormjun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<