dubbo source code analysis 3 -- protocol Protocol

Agreement

The protocol is based on SPI, and its class distribution is as follows:

Exporter<?> exporter = protocol.export(
               proxyFactory.getInvoker(ref, (Class) interfaceClass, local));

Agreement has
DubboProtocol,InjvmProtocol,MemcachedProtocol,MockProtocol,RedisProtocol.ThriftProtocol....

So which agreement does he choose
The first two sections mentioned above will generate a protocol $adaptive class based on bytecode.
At this time, the Invoker determines which class to go according to url.getProtocol(). If not specified, then go to dubbo protocol

public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
   //....
    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) 
      throws com.alibaba.dubbo.rpc.Invoker {
        if (arg0 == null) 
            throw new IllegalArgumentException("..");
        if (arg0.getUrl() == null) 
            throw new IllegalArgumentException("..");
            com.alibaba.dubbo.common.URL url = arg0.getUrl();
            String extName = ( url.getProtocol() == null ?
             "dubbo" : url.getProtocol() );
        if(extName == null) 
            throw new IllegalStateException("..");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)
            ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
            .getExtension(extName);
        return extension.export(arg0);
    }
}

ProtocolListenerWrapper - > protocolfilterwrapper protocol decorator

And there's a decorator outside the protocol, ProtocolListenerWrapper
Except for RegisterProtocol, which is a direct call, the rest should go to ListenerExporterWrapper

public class ProtocolListenerWrapper implements Protocol {

    private final Protocol protocol;

    //....

    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        //If it is RegisterProtocol, call directly
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }

        return new ListenerExporterWrapper<T>(protocol.export(invoker), 
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(
                ExporterListener.class).getActivateExtension(invoker.getUrl(), 
                Constants.EXPORTER_LISTENER_KEY)));
    }

    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        //If it is RegisterProtocol, call directly
        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
            return protocol.refer(type, url);
        }
        return new ListenerInvokerWrapper<T>(protocol.refer(type, url), 
                Collections.unmodifiableList(
                        ExtensionLoader.getExtensionLoader(InvokerListener.class)
                        .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
    }

    public void destroy() {
        protocol.destroy();
    }

}

ListenerInvokerWrapper

public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener>
 listeners{ 
    //... incoming Listeners listening
    if (listeners != null && listeners.size() > 0) {
        RuntimeException exception = null;
        for (ExporterListener listener : listeners) {
            if (listener != null) {
                try {
                    listener.exported(this);
                } catch (RuntimeException t) {
                    logger.error(t.getMessage(), t);
                    exception = t;
                }
            }
        }
        if (exception != null) {
            throw exception;
        }
    }
 }

Which listeners are there

Collections.unmodifiableList(ExtensionLoader.getExtensionLoader
(ExporterListener.class).getActivateExtension(
invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY))

ProtocolFilterWrapper :
Organize a single linked list according to Filter. The front is Filter, and the tail of the chain is the real agent factory Wrapper,

public class ProtocolFilterWrapper implements Protocol {

    private final Protocol protocol;//dubbo,registry

    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        //registry goes native
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
    }

    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        //registry goes native
        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
            return protocol.refer(type, url);
        }
        return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
    }

    public void destroy() {
        protocol.destroy();
    }

    //Key Invoker is a single linked list next
    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        Invoker<T> last = invoker;
        //Get all filters (TimeoutFilter, exceltionfilter, monitorfilter,
        //DubboDataTranferFilter...)
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).
                getActivateExtension(invoker.getUrl(), key, group);
        if (filters.size() > 0) {
            for (int i = filters.size() - 1; i >= 0; i --) {
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                last = new Invoker<T>() {
                    public Class<T> getInterface() {
                        return invoker.getInterface();
                    }

                    public URL getUrl() {
                        return invoker.getUrl();
                    }

                    public boolean isAvailable() {
                        return invoker.isAvailable();
                    }
                    //call
                    public Result invoke(Invocation invocation) throws RpcException {
                        return filter.invoke(next, invocation);
                    }

                    public void destroy() {
                        invoker.destroy();
                    }

                    @Override
                    public String toString() {
                        return invoker.toString();
                    }
                };
            }
        }
        return last;
    }

}

Tags: Dubbo REST

Posted on Mon, 30 Mar 2020 14:59:45 -0700 by obsidian