查看: 95|回复: 0

Dubbo如何支持本地调用?injvm方式解析

[复制链接]
发表于 2020-2-15 22:58:18 | 显示全部楼层 |阅读模式
Dubbo是一个远程调用的框架,对于一个服务提供者,袒露了一个接口供外部消耗者调用,
那么对于提供者自己是否可以调用这个接口,需要什么特殊处理吗?
这篇文章就分享下Dubbo关于本地调用的实现机制,以及如何开启和关闭本地调用。
injvm支持本地调用

利用 Dubbo 本地调用不需做特殊设置,按正常 Dubbo 服务袒露服务即可。
任一服务在袒露远程服务的同时,也会同时以 injvm 的协议袒露本地服务。
injvm 是一个伪协议,不会像其他协议那样对外开启端口,只用于本地调用的目的。
InjvmProtocol源码学习

injvm相干的代码实现在Dubbo-rpc-injvm模块中,主要是InjvmExporter、InjvmInvoker和InjvmProtocol。
InjvmProtocol 继续 AbstractProtocol,
  1. public class InjvmProtocol extends AbstractProtocol implements Protocol {    public static final String NAME = Constants.LOCAL_PROTOCOL;    public static final int DEFAULT_PORT = 0;    private static InjvmProtocol INSTANCE;    public InjvmProtocol() {        INSTANCE = this;    }    public static InjvmProtocol getInjvmProtocol() {        if (INSTANCE == null) {            ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(InjvmProtocol.NAME); // load        }        return INSTANCE;    }    @Override    public  Exporter export(Invoker invoker) throws RpcException {        return new InjvmExporter(invoker, invoker.getUrl().getServiceKey(), exporterMap);    }    @Override    public  Invoker refer(Class serviceType, URL url) throws RpcException {        return new InjvmInvoker(serviceType, url, url.getServiceKey(), exporterMap);    }}
复制代码
除了export和refer方法,InjvmProtocol提供了isInjvmRefer()方法,
isInjvmRefer会读取设置文件,判定是否开启本地调用。
  1.     public boolean isInjvmRefer(URL url) {        String scope = url.getParameter(Constants.SCOPE_KEY);        // Since injvm protocol is configured explicitly, we don't need to set any extra flag, use normal refer process.        if (Constants.SCOPE_LOCAL.equals(scope) || (url.getParameter(Constants.LOCAL_PROTOCOL, false))) {            // if it's declared as local reference            // 'scope=local' is equivalent to 'injvm=true', injvm will be deprecated in the future release            return true;        } else if (Constants.SCOPE_REMOTE.equals(scope)) {            // it's declared as remote reference            return false;        } else if (url.getParameter(Constants.GENERIC_KEY, false)) {            // generic invocation is not local reference            return false;        } else if (getExporter(exporterMap, url) != null) {            // by default, go through local reference if there's the service exposed locally            return true;        } else {            return false;        }    }
复制代码
本地调用同样经过Filter链

与真正的本地方法调用不同的是,Dubbo 本地调用会经过 Filter 链,其中包罗了 Consumer 端的 Filter 链以及 Provider 端的 Filter 链。
通过这样的机制,本地消耗者和其他消耗者都是同一对待,同一监控,服务同一进行管理。

如何开启本地调用

默认情况下,本地调用是主动开启的,不需要做额外的设置。只有只有当需要关闭的时间,才需要通过 scope 的设置来显式的关闭。
但是,特别需要指出的是,在下面的几种情况下,本地调用是无法利用的:
第一,泛化调用的时间无法利用本地调用。
第二,消耗者明确指定 URL 发起直连调用。当然,如果消耗者指定的是 injvm 的 URL,最终的调用也是走本地调用的,比如:
  1. [/code][size=4]如何关闭本地调用[/size]
  2. 本地调用是可以体现关闭的,通过这种方式,服务提供者可以做到对远端服务消耗者和本地消耗者等量齐观。
  3. 详细做法是通过 scope="remote" 来关闭 injvm 协议的袒露,这样,纵然是本地调用者,也需要从注册中心上获取服务地址列表,然后才能发起调用,
  4. 而这个时间的调用过程,与远端的服务消耗者的过程是同等的。
  5. [code]
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?用户注册

x

相关技术服务需求,请联系管理员和客服QQ:2753533861或QQ:619920289
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

帖子推荐:
客服咨询

QQ:2753533861

服务时间 9:00-22:00

快速回复 返回顶部 返回列表