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

資訊專欄INFORMATION COLUMN

Dubbo服務消費者調用過程

B0B0 / 2823人閱讀

摘要:先來說第種類型,即遠程通信的,看的源碼,調用過程大致內容就是將通過遠程通信將信息傳遞給服務器端,服務器端接收到該信息后,找到對應的本地,然后通過反射執行相應的方法,將方法的返回值再通過遠程通信將結果傳遞給客戶端。

上圖是服務消費的主過程:

首先通過ReferenceConfig類的private void init()方法會先檢查初始化所有的配置信息后,調用private T createProxy(Map map)創建代理,消費者最終得到的是服務的代理, 在createProxy接著調用Protocol 接口實現的 Invoker refer(Class type, URL url)方法生成Invoker實例(如上圖中的紅色部分),這是服務消費的關鍵。接下來把Invoker通過ProxyFactory代理工廠轉換為客戶端需要的接口(如:HelloWorld),創建服務代理并返回。

消費端的初始化過程

1、把服務引用的信息封裝成URL并注冊到zk注冊中心;
2、監聽注冊中心的服務的上下線;
3、連接服務提供端,創建NettyClient對象;
4、將這些信息包裝成DubboInvoker消費端的調用鏈,創建消費端Invoker實例的服務代理并返回;

消費端的服務引用過程

1、經過負載均衡策略,調用提供者;
2、選擇其中一個服務的URL與提供者netty建立連接,使用ProxyFactory 創建遠程通信,或者本地通信的,Invoker發到netty服務端;
3、服務器端接收到該Invoker信息后,找到對應的本地Invoker,處理Invocation請求;
4、獲取異步,或同步處理結果;

異步 不需要返回值:直接調用ExchangeClient.send()方法;

同步 需要返回值:使用ExchangeClient.request()方法,返回一個ResponseFuture,一直阻塞到服務端返回響應結果;

案例介紹

先看一個簡單的客戶端引用服務的例子,HelloServicedubbo配置如下:




使用Zookeeper作為注冊中心

引用遠程的HelloService接口服務

根據之前的介紹,在Spring啟動的時候,根據配置會創建一個ReferenceBean,該bean又實現了Spring的FactoryBean接口,所以我們如下方式使用時:

@Autowired
private HelloService helloService;

使用的不是ReferenceBean對象,而是ReferenceBean的getObject()方法返回的對象,該對象通過代理實現了HelloService接口,所以要看服務引用的整個過程就需要從ReferenceBean.getObject()方法開始入手。

服務引用過程

將ReferenceConfig.init()中的內容拆成具體的步驟,如下:

第一步:收集配置參數
methods=hello,
timestamp=1443695417847,
dubbo=2.5.3
application=consumer-of-helloService
side=consumer
pid=7748
interface=com.demo.dubbo.service.HelloService
第二步:從注冊中心獲取服務地址,返回Invoker對象

如果是單個注冊中心,代碼如下:

Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

invoker = refprotocol.refer(interfaceClass, url);

上述url的內容如下:

registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?
application=consumer-of-helloService&
dubbo=2.5.6&
pid=8292&
registry=zookeeper&
timestamp=1443707173909&

refer=
    application=consumer-of-helloService&
    dubbo=2.5.6&
    interface=com.demo.dubbo.service.HelloService&
    methods=hello&
    pid=8292&
    side=consumer&
    timestamp=1443707173884&
第三步:使用ProxyFactory創建出Invoker的代理對象
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

proxyFactory.getProxy(invoker);

下面就詳細說明下上述提到的幾個概念:Protocol、Invoker、ProxyFactory

概念介紹 Invoker

Invoker是一個可執行對象,有三種類型的Invoker:

本地執行的Invoker(服務端使用)

遠程通信執行的Invoker(客戶端使用)

多個類型2的Invoker聚合成的集群版Invoker(客戶端使用)

Invoker的實現情況如下:

先來看服務引用的第2個步驟,返回Invoker對象

對于客戶端來說,Invoker應該是2、3這兩種類型。先來說第2種類型,即遠程通信的Invoker,看DubboInvoker的源碼,調用過程AbstractInvoker.invoke()->doInvoke():

    protected Result doInvoke(final Invocation invocation) throws Throwable {
        RpcInvocation inv = (RpcInvocation) invocation;
        final String methodName = RpcUtils.getMethodName(invocation);
        inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
        inv.setAttachment(Constants.VERSION_KEY, version);

        ExchangeClient currentClient;
        if (clients.length == 1) {
            currentClient = clients[0];
        } else {
            currentClient = clients[index.getAndIncrement() % clients.length];
        }
        try {
            boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
            int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY,Constants.DEFAULT_TIMEOUT);
            if (isOneway) {
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                currentClient.send(inv, isSent);
                RpcContext.getContext().setFuture(null);
                return new RpcResult();
            } else if (isAsync) {
                ResponseFuture future = currentClient.request(inv, timeout) ;
                RpcContext.getContext().setFuture(new FutureAdapter(future));
                return new RpcResult();
            } else {
                RpcContext.getContext().setFuture(null);
                return (Result) currentClient.request(inv, timeout).get();
            }
        } catch (TimeoutException e) {
            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        } catch (RemotingException e) {
            throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

大致內容就是:
將通過遠程通信將Invocation信息傳遞給服務器端,服務器端接收到該Invocation信息后,找到對應的本地Invoker,然后通過反射執行相應的方法,將方法的返回值再通過遠程通信將結果傳遞給客戶端。

這里分3種情況:

執行方法不需要返回值:直接調用ExchangeClient.send()方法。

執行方法的結果需要異步返回:使用ExchangeClient.request()方法返回一個ResponseFuture對象,通過RpcContext中的ThreadLocal使ResponseFuture和當前線程綁定,未等服務端響應結果就直接返回,然后服務端通過ProtocolFilterWrapper.buildInvokerChain()方法會調用Filter.invoke()方法,即FutureFilter.invoker()->asyncCallback(),會獲取RpcContextResponseFuture對象,異步返回結果。

執行方法的結果需要同步返回:使用ExchangeClient.request()方法,返回一個ResponseFuture,一直阻塞到服務端返回響應結果

Protocol

服務引用的第二步就是:

Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

invoker = refprotocol.refer(interfaceClass, url);

使用協議Protocol根據上述的url和服務接口來引用服務,創建出一個Invoker對象

默認實現的DubboProtocol也會經過ProtocolFilterWrapper、ProtocolListenerWrapper、RegistryProtocol的包裝

首先看下RegistryProtocol.refer()方法,它干了哪些事呢?

將客戶端的信息注冊到注冊中心上

創建一個RegistryDirectory,從注冊中心中訂閱自己引用的服務,將訂閱到的url在RegistryDirectory內部轉換成Invoker。

RegistryDirectory是Directory的實現,Directory代表多個Invoker,可以把它看成List類型的Invoker,但與List不同的是,它的值可能是動態變化的,比如注冊中心推送變更RegistryDirectory內部含有兩者重要屬性:

注冊中心服務Registry

Protocol 它會利用注冊中心服務Registry來獲取最新的服務器端注冊的url地址,然后再利用協議Protocol將這些url地址轉換成一個具有遠程通信功能的Invoker對象,如DubboInvoker

在Directory的基礎上使用Cluster將上述多個Invoker對象聚合成一個集群版的Invoker對象

Directory和Cluster都是服務治理的重點,接下去會多帶帶拿一章出來講

ProxyFactory

服務引用的第三步就是:

proxyFactory.getProxy(invoker);

對于Server端,ProxyFactory主要負責將服務如HelloServiceImpl統一進行包裝成一個Invoker,這些Invoker通過反射來執行具體的HelloServiceImpl對象的方法

對于client端,則是將上述創建的集群版Invoker(Cluster)創建出代理對象

代碼如下:

public class JavassistProxyFactory extends AbstractProxyFactory {

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

可以看到是利用jdk自帶的Proxy來動態代理目標對象Invoker,所以我們調用創建出來的代理對象如HelloService的方法時,會執行InvokerInvocationHandler中的邏輯:

public class InvokerInvocationHandler implements InvocationHandler {

    private final Invoker invoker;

    public InvokerInvocationHandler(Invoker handler){
        this.invoker = handler;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }
        //AbstractClusterInvoker.invoke()
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }

}

參考:http://dubbo.apache.org/books/dubbo-dev-book/implementation.html
參考:https://my.oschina.net/xiaominmin/blog/1599378

Contact

作者:鵬磊

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

版權歸作者所有,轉載請注明出處

Wechat:關注公眾號,搜云庫,專注于開發技術的研究與知識分享

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71193.html

相關文章

  • 基于Dubbo+ZooKeeper的分布式服務的實現

    摘要:調用流程服務容器負責啟動,加載,運行服務提供者。服務提供者在啟動時,向注冊中心注冊自己提供的服務。注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數據給消費者。這就是分布式服務注冊中心的由來。 Dubbo是什么 一款分布式服務框架 高性能和透明化的RPC遠程服務調用方案。這里簡單介紹一下RPC,所謂RPC就是遠程過程調用,全稱為Romate Proce...

    warkiz 評論0 收藏0
  • 基于Dubbo+ZooKeeper的分布式服務的實現

    摘要:調用流程服務容器負責啟動,加載,運行服務提供者。服務提供者在啟動時,向注冊中心注冊自己提供的服務。注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數據給消費者。這就是分布式服務注冊中心的由來。 Dubbo是什么 一款分布式服務框架 高性能和透明化的RPC遠程服務調用方案。這里簡單介紹一下RPC,所謂RPC就是遠程過程調用,全稱為Romate Proce...

    enda 評論0 收藏0
  • Dubbo服務暴露過程

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

    bigdevil_s 評論0 收藏0
  • 構建springmvc+myabtis+dubbo分布式平臺-dubbo簡介

    摘要:服務自動注冊與發現,不再需要寫死服務提供方地址,注冊中心基于接口名查詢服務提供者的地址,并且能夠平滑添加或刪除服務提供者。調用關系說明服務容器負責啟動,加載,運行服務提供者。服務提供者在啟動時,向注冊中心注冊自己提供的服務。 上一篇我們介紹《構建dubbo分布式平臺-maven構建ant-utils工具包的構建》,從今天開始,我們進入分布式服務項目的核心教程,真正使用dubbo實現分布...

    鄒立鵬 評論0 收藏0

發表評論

0條評論

B0B0

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<