Dubbo2.7.6之服务暴露详细过程解析

继上一篇Dubbo2.7.6之服务暴露流程 之后,这里就详细讨论服务暴露的过程。由于官方建议注册中心为zookeeper。那么这里就以zookeeper为注册中心。来看一下暴露服务到zookeeper中的详细过程。

在ServiceConfig中,暴露服务的核心逻辑就是三行代码。如下:

//1 使用ProxyFactory来生产一个Invoker实例
Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass,  registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
//2 使用DelegateProviderMetaDataInvoker来包装Invoker,将Invoker委派给DelegateProviderMetaDataInvoker
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
//3 使用Protocol实例来暴露服务
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);

那么下面就分三步来研究:

  1. 生成Invoker实例

实际调用的是StubProxyFactoryWrapper#getInvoker(T proxy, Class type, URL url)方法。

参数解释:
proxy 服务接口的实现类
type 服务接口,必须是接口
URL 服务注册的所有配置信息

具体实现:

public class StubProxyFactoryWrapper implements ProxyFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(StubProxyFactoryWrapper.class);

    private final ProxyFactory proxyFactory;

    private Protocol protocol;

    public StubProxyFactoryWrapper(ProxyFactory proxyFactory) {
        this.proxyFactory = proxyFactory;
    }

    public void setProtocol(Protocol protocol) {
        this.protocol = protocol;
    }

    ...
    /**
    *
    * 调用被包装的ProxyFactory实例的getInvoker方法
    * 也就是JavassistProxyFactory#getInvoker(T proxy, Class<T> type, URL url)
    **/
    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
        return proxyFactory.getInvoker(proxy, type, url);
    }

    private <T> Exporter<T> export(T instance, Class<T> type, URL url) {
        return protocol.export(proxyFactory.getInvoker(instance, type, url));
    }

}

其实具体逻辑还是在JavassistProxyFactory中,那就继续看它的实现:

public class JavassistProxyFactory extends AbstractProxyFactory {

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

    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
        //生成接口的Wrapper类,这里又会通过字节码技术,重新生产一个对应服务接口的wrapper类class实例
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);  
        //构建一个AbstractProxyInvoker实例,这里又使用了模版设计模式。自实现模版方法doInvoke
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }

}

也就是说,第一步产生了一个AbstractProxyInvoker实例。

  1. 创建Invoker包装类 DelegateProviderMetaDataInvoker

DelegateProviderMetaDataInvoker是一个Invoker的包装类,它的作用就是将服务接口的Invoker实例和ServiceConfig实例包装在一起。

/**
 *
 * A Invoker wrapper that wrap the invoker and all the metadata (ServiceConfig)
 */
public class DelegateProviderMetaDataInvoker<T> implements Invoker {
    protected final Invoker<T> invoker;
    private ServiceConfig<?> metadata;

    public DelegateProviderMetaDataInvoker(Invoker<T> invoker, ServiceConfig<?> metadata) {
        this.invoker = invoker;
        this.metadata = metadata;
    }

    @Override
    public Class<T> getInterface() {
        return invoker.getInterface();
    }

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

    @Override
    public boolean isAvailable() {
        return invoker.isAvailable();
    }
    /**
    * Inocation就是对要调用方法的包装。里面包含的接口方法的名称,参数类型,参数等信息
    * 
    * 这里就是对要调用具体方法的执行逻辑
    **/
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        return invoker.invoke(invocation);
    }

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

    public ServiceConfig<?> getMetadata() {
        return metadata;
    }
}
  1. export服务

这是Protocol在暴露服务接口时,默认的实现结构图。

在这里插入图片描述
在使用PROTOCOL获取暴露接口时,实际上PROTOCOL是一个包装类。最底层包含了DubboProtocol。 使用QosProtocolWrapper,ProtocolFilterWrapper,ProtocolListenerWrapper这三个包装类一层一层的包装DubboProtocol 。这里就使用到了装饰者设计模式。在每一层都会添加额外的处理逻辑。结构如下:
在这里插入图片描述
下面先来看源码QosProtocolWrapper:

public class QosProtocolWrapper implements Protocol {

    private final Logger logger = LoggerFactory.getLogger(QosProtocolWrapper.class);
    private static AtomicBoolean hasStarted = new AtomicBoolean(false);
    private Protocol protocol;
    public QosProtocolWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }
    ...
    
    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        //如果是应用注册,则启动Qos服务
        if (UrlUtils.isRegistry(invoker.getUrl())) {
            startQosServer(invoker.getUrl());
            return protocol.export(invoker);
        }
        //暴露接口就直接调用自己包装的Protocol实例的export方法
        return protocol.export(invoker);
    }
   ...
}

可以看到在暴露具体接口服务时,这个wrapper是直接调用ProtocolFilterWrapper#export(),相当于没有执行任何逻辑。下面继续看ProtocolFilterWrapper#export

public class ProtocolFilterWrapper implements Protocol {

    private final Protocol protocol;
    public ProtocolFilterWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }


    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        //如果是应用注册,就调下一层Protocol实例
        if (UrlUtils.isRegistry(invoker.getUrl())) {
            return protocol.export(invoker);
        }
        //如果暴露接口服务,就构建InvokerChain
        return protocol.export(buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER));
    }
    //获取所有的可激活的filter,然后一层一层包装Invoker实例,构成一个InvokerChian
    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        Invoker<T> last = invoker;
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);

        if (!filters.isEmpty()) {
            for (int i = filters.size() - 1; i >= 0; i--) {
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                last = new Invoker<T>() {

                    @Override
                    public Class<T> getInterface() {
                        return invoker.getInterface();
                    }

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

                    @Override
                    public boolean isAvailable() {
                        return invoker.isAvailable();
                    }

                    @Override
                    public Result invoke(Invocation invocation) throws RpcException {
                        Result asyncResult;
                        try {
                            asyncResult = filter.invoke(next, invocation);
                        } catch (Exception e) {
                            if (filter instanceof ListenableFilter) {
                                ListenableFilter listenableFilter = ((ListenableFilter) filter);
                                try {
                                    Filter.Listener listener = listenableFilter.listener(invocation);
                                    if (listener != null) {
                                        listener.onError(e, invoker, invocation);
                                    }
                                } finally {
                                    listenableFilter.removeListener(invocation);
                                }
                            } else if (filter instanceof Filter.Listener) {
                                Filter.Listener listener = (Filter.Listener) filter;
                                listener.onError(e, invoker, invocation);
                            }
                            throw e;
                        } finally {

                        }
                        return asyncResult.whenCompleteWithContext((r, t) -> {
                            if (filter instanceof ListenableFilter) {
                                ListenableFilter listenableFilter = ((ListenableFilter) filter);
                                Filter.Listener listener = listenableFilter.listener(invocation);
                                try {
                                    if (listener != null) {
                                        if (t == null) {
                                            listener.onResponse(r, invoker, invocation);
                                        } else {
                                            listener.onError(t, invoker, invocation);
                                        }
                                    }
                                } finally {
                                    listenableFilter.removeListener(invocation);
                                }
                            } else if (filter instanceof Filter.Listener) {
                                Filter.Listener listener = (Filter.Listener) filter;
                                if (t == null) {
                                    listener.onResponse(r, invoker, invocation);
                                } else {
                                    listener.onError(t, invoker, invocation);
                                }
                            }
                        });
                    }

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

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

        return last;
    }

ProtocolFilterWrapper将Filter封装进Invoker中之后,再调用被它包装的Protocol实例ProtocolListenerWrapper的export方法。
下面来看下这里面的实现逻辑:

public class ProtocolListenerWrapper implements Protocol {

    private final Protocol protocol;

    public ProtocolListenerWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }
    ...
    
    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        //如果应用注册,就跳过此Wrapper逻辑。
        if (UrlUtils.isRegistry(invoker.getUrl())) {
            return protocol.export(invoker);
        }
        //如果服务接口注册,则获取到所有的可激活的ExporterListener实例。使用ListenerExporterWrapper再此wrapper起来
        return new ListenerExporterWrapper<T>(protocol.export(invoker),
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
                        .getActivateExtension(invoker.getUrl(), EXPORTER_LISTENER_KEY)));
    }
}

直接看ListenerExporterWrapper实现:

public class ListenerExporterWrapper<T> implements Exporter<T> {

    private static final Logger logger = LoggerFactory.getLogger(ListenerExporterWrapper.class);

    private final Exporter<T> exporter;

    private final List<ExporterListener> listeners;
    
    public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener> listeners) {
        if (exporter == null) {
            throw new IllegalArgumentException("exporter == null");
        }
        this.exporter = exporter;
        this.listeners = listeners;
        if (CollectionUtils.isNotEmpty(listeners)) {
            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;
            }
        }
    }
    @Override
    public Invoker<T> getInvoker() {
        return exporter.getInvoker();
    }

 ...
}

可以看到,在ListenerExporterWrapper的构造方法中,对ExporterListener进行了逐个调用。但是目前ExporterListener 的没有具体实现。也就是这段逻辑就是包装了一下exporter实例。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值