三Dubbo服务暴露源码分析--2本地暴露

三Dubbo服务暴露源码分析--2本地暴露

3.1 本地暴露(exportLocal)

ServiceConfig

    private void exportLocal(URL url) {
  		//url中protocol如果不为injvm,重新设置URL为injvm://的协议头
        if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
          //转换前 dubbo://192.168.0.101:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=20987&side=provider&timestamp=1671167576621
          //injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=20987&side=provider&timestamp=1671167576621 
          //将协议头更换为injvm;地址192.168.0.101:20880更换为127.0.0.1
            URL local = URL.valueOf(url.toFullString())
                    .setProtocol(Constants.LOCAL_PROTOCOL)
                    .setHost(NetUtils.LOCALHOST)
                    .setPort(0);
//TAG1 getAdaptiveExtension(@SPI自适应)
//TAG2 proxyFactory.getInvoker---创建invoker
//TAG3 protocol.export---invoker转换为exporter
            Exporter<?> exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
            exporters.add(exporter);
            logger.info("Export dubbo service " + interfaceClass.getName() +" to local registry");
        }
    }
TAG1 getAdaptiveExtension(@SPI自适应)

image-20221216143458371

此时,protocol的实现类是Dubbo机制创建的动态自适应类Protocol$Adpative。

ServiceConfig
   private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
@SPI("dubbo")
public interface Protocol {
    
    /**
     * 获取缺省端口,当用户没有配置端口时使用。
     * 
     * @return 缺省端口
     */
    int getDefaultPort();

    /**
     * 暴露远程服务:<br>
     * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
     * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>
     * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>
     * 
     * @param <T> 服务的类型
     * @param invoker 服务的执行体
     * @return exporter 暴露服务的引用,用于取消暴露
     * @throws RpcException 当暴露服务出错时抛出,比如端口已占用
     */
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

根据dubbo的@SPI机制,@Adaptive加在服务接口方法上,调用getAdaptiveExtension方法,会构建字节码,创建一个动态编译的adaptive类。

TAG1.1 Adaptive动态编译源码处理

将服务端log4j.xml配置文件内的log级别设置为DEBUG,

image-20221216144753266

设置log4j的级别为debug原因,

image-20221216145059472

此时,logger.debug会输出创建动态编译的adaptive的字节码。

然后再provider端的java文件夹下,创建对应的package,并复制console中输出的log信息,重建动态编译类,在方法调用处打断点,然后重启代码

image-20221216150649224

image-20230310182126314

TAG2 proxyFactory.getInvoker---ref服务转换invoker
//TAG1 getAdaptiveExtension(@SPI自适应)
//TAG2 proxyFactory.getInvoker---创建invoker
//TAG3 protocol.export---invoker转换为exporter
            Exporter<?> exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));

image-20221216151201688

方法参数如上:

public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {

    public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2) throws RpcException {
        if (arg2 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg2;
      //ProxyFactory的@spi拓展名为javassist
        String extName = url.getParameter("proxy", "javassist");
        if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
      
//TAG2.1 ProxyFactory自适应类--stubProxyFactoryWrapper
      //创建ProxyFactory的javassist自适应类
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
//TAG2.2 proxyFactory.getInvoker
        return extension.getInvoker(arg0, arg1, arg2);
    }
}
TAG2.1 ProxyFactory自适应类--stubProxyFactoryWrapper(Wrapper机制)
@SPI("javassist")
public interface ProxyFactory {
     /** create invoker.
     * 
     * @param <T>
     * @param proxy
     * @param type
     * @param url
     * @return invoker
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}

ProxyFactory的方法上有@Adaptive({Constants.PROXY_KEY})标记,其会在执行getExtension(extName)时,创建动态编译类ProxyFactory$Adpative;其内代理方法,调用ExtensionLoader.getExtensionLoader.getExtension(extName)创建自适应实例。

image-20221216152400137

这里,ProxyFactory为StubProxyFactoryWrapper,是@SPI的wrapper机制。

image-20221216153517859

wrapper机制,会在JavassistProxyFactory加上包装

image-20221216153820953

TAG2.2 JavassistProxyFactory.getInvoker
StubProxyFactoryWrapper
  
      private final ProxyFactory proxyFactory;

   public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
        return proxyFactory.getInvoker(proxy, type, url);
    }

image-20221216154117169

public class JavassistProxyFactory extends AbstractProxyFactory {

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // TODO Wrapper类不能正确处理带$的类名
//TAG2.2.1 Wrapper.getWrapper
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
//TAG2.2.2. AbstractProxyInvoker
        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);
            }
        };
    }
//TAG2.2.1 Wrapper.getWrapper--prov实例包装

将传入的服务端服务实例serviceImpl,字节码构造,并创建invokeMethod方法,调用服务时,根据方法名称遍历,执行最终调用。

详情看Wrapper.getWrapper的原理。

//TAG2.2.2. AbstractProxyInvoker--服务端本地暴露匿名类invoker
//invoker的包装类----invoker负责将对服务的调用,代理到invoker上的invoke方法
public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
  
    public Result invoke(Invocation invocation) throws RpcException {
        try {
          //调用invoke,返回RpcResult结果
            return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
        } catch (InvocationTargetException e) {
            return new RpcResult(e.getTargetException());
        } catch (Throwable e) {
            throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
    
  //具体调用,由子类实现
    protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;
    
}

所以,服务本地暴露的匿名类AbstractProxyInvoker,重写doInvoke方法

//TAG2.2.2. AbstractProxyInvoker
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName, 
                                      Class<?>[] parameterTypes, 
                                      Object[] arguments) throws Throwable {
              //provider端invoker.invoke调用,代理到wrapper(ref实现类)的invokeMethod上
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }
TAG3 Protocol$Adpative.export---invoker转换为exporter
//TAG1 getAdaptiveExtension(@SPI自适应)
//TAG2 proxyFactory.getInvoker---创建invoker
//TAG3 protocol.export---invoker转换为exporter
            Exporter<?> exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));

然后执行protocol.export(invoker),暴露服务,可知此时invoker实例为如下(AbstractProxyInvoker匿名类)

image-20221216155745505

public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
      //获取invoker内的服务的url
      //injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=25677&side=provider&timestamp=1671174564948
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
      //protocol协议injvm
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
      
//TAG3.1 Protocol自适应类(listener、wrapper)
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
//TAG3.2 protocol.export
        return extension.export(arg0);
    }
TAG3.1 Protocol自适应类(listener、wrapper)

image-20221216164627763

会再getExtension时,会先包裹filter,再包裹listener类

image-20221216164731150

TAG3.2 listenerProtocol.export(listener->filter->injvm)
public class ProtocolListenerWrapper implements Protocol {
    private final Protocol protocol;

    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
//TAG3.2.1 filterprotocol.export
//TAG3.2.2 ListenerExporterWrapper
        return new ListenerExporterWrapper<T>(protocol.export(invoker), 
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
                        .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
    }

ProtocolListenerWrapper的export方法的作用,是当服务被protocol.export暴露后,创建ListenerExporterWrapper对象(该对象是exporter和ExporterListener的包装类,exporter是服务暴露的对象,由protocol.export(invoker)执行;ExporterListener是针对该exporter的监听器),protocol.export后,会执行其构造函数,会逐个的执行监听器的exposed方法--------上述过程,实现在服务被protocol.export暴露后,ExporterListener监听器执行相应的监听暴露exposed方法。

image-20221216174420642

TAG3.2.1 filterprotocol.export
ProtocolFilterWrapper
  
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
  			//如果protocol协议为registry,则直接protocol.export暴露--(registry表示需要注册,而不是构造拦截器链并export暴露)
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
  
//TAG3.2.1.1 buildInvokerChain
//TAG3.2.1.2 injvmProtocol.export
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
    }
//TAG3.2.1.1 buildInvokerChain--构造拦截器链

方法参数:

image-20221216185621694

ProtocolFilterWrapper
 private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {

        Invoker<T> last = invoker;
  			//获取已经自动激活的filter对象
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
        if (filters.size() > 0) {
          //倒序遍历filter,最后一个filter所构造的invoker,执行invoke时,是filter.invoke(next,invocation)。
            for (int i = filters.size() - 1; i >= 0; i --) {
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                last = new Invoker<T>() {

/** ……………………………………………将filter构造为invoker拦截器链,其方法,获取都是当前abstractProxyInvoker匿名类的属性…………………………………………*/
                    public Class<T> getInterface() {
                        return invoker.getInterface();
                    }
                    public URL getUrl() {
                        return invoker.getUrl();
                    }
                    public boolean isAvailable() {
                        return invoker.isAvailable();
                    }
                    public void destroy() {
                        invoker.destroy();
                    }
                    @Override
                    public String toString() {
                        return invoker.toString();
                    }
/**………………………………………………………………………………………………………………………链式调用的实现………………………………………………………………………………………………………………………… */
                    public Result invoke(Invocation invocation) throws RpcException {
   //倒序遍历filter,最后一个filter的执行,会调用filter.invoke(next,invocation),next为abstractProxyInvoker,则加入filter末尾
                        return filter.invoke(next, invocation);
                    }

                };
            }
        }
        return last;
    }

注意上面构造filter链的顺序:

provider端的服务invoker----abstractProxyInvoker匿名类,加入filter的末尾,并返回头invoker。

active的filter如下:

image-20221217105743073

构造后的拦截器链如下所示:

image-20221218011118836

总结上面的filter链的构造,对服务的包裹结构,如下:

image-20230310182235429

最内层的ref是provider端服务的实现类impl,由内到外是dubbo框架进行的包装。

//TAG3.2.1.2 injvmProtocol.export--暴露服务
ProtocolFilterWrapper
//TAG3.2.1.1 buildInvokerChain
//TAG3.2.1.2 injvmProtocol.export
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));

在对abstractproxyInvoker包装上filter的invoker,并构成过滤器链后,执行protocol.export暴露服务。

public abstract class AbstractProtocol implements Protocol {
  //在protocol中缓存exporter
	protected final Map<String, Exporter<?>> exporterMap = new ConcurrentHashMap<String, Exporter<?>>();
  protected final Set<Invoker<?>> invokers = new ConcurrentHashSet<Invoker<?>>();

  
InjvmProtocol
   public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
//TAG3.2.1.2.1 InjvmExporter(构造exporter对象)
        return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
    }
//TAG3.2.1.2.1 InjvmExporter(构造exporter对象)

此时,构造InjvmExporter对象,并对exporter做缓存,存入exporterMap。传入的servicekey为当前provider服务接口,map中的value为暴露的exporter对象。

image-20221218112901886

class InjvmExporter<T> extends AbstractExporter<T> 

    InjvmExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap){
        super(invoker);
        this.key = key;
        this.exporterMap = exporterMap;
  		//将服务接口为key;InjvmExporter为value,存入exporterMap中
        exporterMap.put(key, this);
    }
    
    //exporter父类
    public abstract class AbstractExporter<T> implements Exporter<T> 
    private final Invoker<T> invoker;

image-20221218113857681

TAG3.2.2 ListenerExporterWrapper

然后回到TAG3.2过程中。在服务被protocol暴露后,会由ExporterListener监听器执行对应的监听方法。

public class ProtocolListenerWrapper implements Protocol {
//TAG3.2.1 filterprotocol.export
//TAG3.2.2 ListenerExporterWrapper
        return new ListenerExporterWrapper<T>(protocol.export(invoker), 
                //unmodifiableList方法,返回内部列表的不可修改的list视图(只读)
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
//TAG3.2.2.1 getActivateExtension(ExtensionLoader机制)
                        .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
//TAG3.2.2.1 getActivateExtension(ExtensionLoader机制)
ExtensionLoader
    public List<T> getActivateExtension(URL url, String key) {
        return getActivateExtension(url, key, null);
    }

此时,参数如下:

image-20221218115230362

   public List<T> getActivateExtension(URL url, String key, String group) {
     //获取invoker.url内参数map内,key="exporter.listener",其value为对应的监听器名称
        String value = url.getParameter(key);
        return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group);
    }

这里是,获取当前invoker.url上配置的key="exporter.listener",针对该特定invoker的监听器,而不是dubbo内的全部监听器。

//TAG3.2.2.2 ListenerExporterWrapper--监听exporter暴露并执行listener.exported通知
public class ListenerExporterWrapper<T> implements Exporter<T> {
  
    private final Exporter<T> exporter;
    private final List<ExporterListener> listeners;

  //invoker在服务暴露后,执行构造函数,在实例化过程中,调用active激活状态的,且invoker.url内配置的所有ExporterListener的exporede方法
    public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener> listeners){
        if (exporter == null) {
            throw new IllegalArgumentException("exporter == null");
        }
      //传入暴露服务的exporter
        this.exporter = exporter;
        this.listeners = listeners;
        if (listeners != null && listeners.size() > 0) {
            RuntimeException exception = null;
          //遍历当前invoker上配置的所有listener
            for (ExporterListener listener : listeners) {
                if (listener != null) {
                    try {
                      //当服务暴露时,执行listener的exported方法
                        listener.exported(this);
                    } catch (RuntimeException t) {
                        logger.error(t.getMessage(), t);
                        exception = t;
                    }
                }
            }
            if (exception != null) {
                throw exception;
            }
        }
    }

invoker在服务暴露后,执行构造函数,在实例化过程中,调用active激活状态的,且invoker.url内配置的所有ExporterListener的exporede方法,达到protocol.export后,通知listener的作用。

TAG0 exportLocal
ServiceConfig
//服务端缓存当前暴露的服务Exporter的list列表
    private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();

    private void exportLocal(URL url) {
        if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
            URL local = URL.valueOf(url.toFullString())
                    .setProtocol(Constants.LOCAL_PROTOCOL)
                    .setHost(NetUtils.LOCALHOST)
                    .setPort(0);
            Exporter<?> exporter = protocol.export(
                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
          
            exporters.add(exporter);
            logger.info("Export dubbo service " + interfaceClass.getName() +" to local registry");
        }
    }

执行后exporters内对象如下:

image-20221218121046791

image-20221218121310278

posted @ 2023-03-13 14:41  LeasonXue  阅读(84)  评论(0编辑  收藏  举报