How does Dubbo support local calls? Analysis of injvm mode

Dubbo is a framework for remote calls. For a service provider, an interface is exposed for external consumers to call,
Do you need any special handling for whether the provider can call this interface?

This article will share Dubbo's implementation mechanism of local call and how to turn it on and off.

injvm supports local calls

Using Dubbo local call does not need special configuration, just expose the service according to the normal Dubbo service.
When any service exposes remote service, it also exposes local service with the protocol of injvm.
injvm is a pseudo protocol. It does not open ports as other protocols do. It is only used for local calls.

Learning the source code of InjvmProtocol

The code related to injvm is implemented in Dubbo RPC injvm module, mainly including InjvmExporter, InjvmInvoker and InjvmProtocol.

InjvmProtocol inherits AbstractProtocol,

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 <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
    }

    @Override
    public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
        return new InjvmInvoker<T>(serviceType, url, url.getServiceKey(), exporterMap);
    }
}

In addition to the export and refer methods, InjvmProtocol provides the isInjvmRefer() method,

isInjvmRefer will read the configuration file to determine whether to start the local call.

    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;
        }
    }

The local call also passes through the Filter chain

Different from the real local method call, the Dubbo local call passes through the Filter chain, including the Filter chain on the Consumer side and the Filter chain on the Provider side.

Through such a mechanism, local consumers and other consumers are treated, monitored and governed in a unified way.

How to enable local call

By default, local calls are enabled automatically, and no additional configuration is required. Only when you need to close it, you need to explicitly close it through the scope configuration.

However, in particular, local calls are not available in the following cases:

First, you can't use a local call when you make a generic call.

Second, the consumer explicitly specifies the URL to initiate a direct connection call. Of course, if the URL specified by the consumer is the URL of the injvm, the final call is also local, such as:

<Dubbo:reference id="demoService" interface="org.apache.Dubbo.samples.local.api.DemoService" url="injvm://127.0.0.1/org.apache.Dubbo.samples.local.api.DemoService"/>

How to close a local call

The local call can show the shutdown. In this way, the service provider can treat the remote service consumer and the local consumer equally.

The specific method is to close the exposure of the injvm protocol through scope="remote", so that even the local caller needs to obtain the service address list from the registry before initiating the call,

At this time, the calling process is consistent with that of the remote service consumer.

<bean id="target" class="org.apache.Dubbo.samples.local.impl.DemoServiceImpl"/>
<!-- Service provider designation scope="remote" -->
<Dubbo:service interface="org.apache.Dubbo.samples.local.api.DemoService" ref="target" scope="remote"/>
<Dubbo:reference id="demoService" interface="org.apache.Dubbo.samples.local.api.DemoService"/>

Tags: Java Dubbo Apache

Posted on Tue, 04 Feb 2020 06:36:54 -0500 by gclx