欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【dubbo】 dubbo Filter 如何根据环境指定自己的Filters (其他SPI接口同理)

程序员文章站 2022-03-10 17:54:32
1 先说解决方案(2.7.3 版本)全局指定直接使用 就可以了;如果是service单独指定可如下配置,consumer端类似2 为什么?一起来看看,filter过滤链的构造过程(2.7.3 版本)执行流程是:org.apache.dubbo.config.ServiceConfig 类加载时jvm 实例化 final protocol--> private static final Protocol protocol = ExtensionLoader.getExtensi...

1 先说解决方案(2.7.3 版本)

  • 全局指定直接使用
    <dubbo:consumer filter="filter1,filter2"/> 
    就可以了;
  • 如果是service单独指定可如下配置,consumer端类似

【dubbo】 dubbo Filter 如何根据环境指定自己的Filters (其他SPI接口同理)

2 为什么?一起来看看,filter过滤链的构造过程(2.7.3 版本)

  • 执行流程是:
  • org.apache.dubbo.config.ServiceConfig 类加载时jvm 实例化 final protocol
  • --> private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); // 类加载时执行
  • --> org.apache.dubbo.common.extension.ExtensionLoader // new 关键字实例化 jvm 执行用户自定义构造方法
  • --> org.apache.dubbo.common.extension.ExtensionLoader#ExtensionLoader
  • --> ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() // 下面会 对SPI相关的文件对应的类进行加载并缓存
  • --> org.apache.dubbo.common.extension.ExtensionLoader#getAdaptiveExtension
  • --> org.apache.dubbo.common.extension.ExtensionLoader#createAdaptiveExtension
  • --> org.apache.dubbo.common.extension.ExtensionLoader#getAdaptiveExtensionClass // 加载自适应扩展类
  • --> org.apache.dubbo.common.extension.ExtensionLoader#getExtensionClasses
  • --> org.apache.dubbo.common.extension.ExtensionLoader#loadExtensionClasses // load 同步执行
  • --> org.apache.dubbo.common.extension.ExtensionLoader#loadExtensionClasses
  • --> org.apache.dubbo.common.extension.ExtensionLoader#loadDirectory // 加载目录文件
  • // 主要涉及三个目录
  1. private static final String SERVICES_DIRECTORY = "META-INF/services/";
  2. private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
  3. private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
  • // 而默认的所有过滤器都在/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter 里面 2.7.3 默认配置如下
  1 cache=org.apache.dubbo.cache.filter.CacheFilter
  2 validation=org.apache.dubbo.validation.filter.ValidationFilter
  3 echo=org.apache.dubbo.rpc.filter.EchoFilter^M
  4 generic=org.apache.dubbo.rpc.filter.GenericFilter^M
  5 genericimpl=org.apache.dubbo.rpc.filter.GenericImplFilter^M
  6 token=org.apache.dubbo.rpc.filter.TokenFilter^M
  7 accesslog=org.apache.dubbo.rpc.filter.AccessLogFilter^M
  8 activelimit=org.apache.dubbo.rpc.filter.ActiveLimitFilter^M
  9 classloader=org.apache.dubbo.rpc.filter.ClassLoaderFilter^M
 10 context=org.apache.dubbo.rpc.filter.ContextFilter^M
 11 consumercontext=org.apache.dubbo.rpc.filter.ConsumerContextFilter^M
 12 exception=org.apache.dubbo.rpc.filter.ExceptionFilter^M
 13 executelimit=org.apache.dubbo.rpc.filter.ExecuteLimitFilter^M
 14 deprecated=org.apache.dubbo.rpc.filter.DeprecatedFilter^M
 15 compatible=org.apache.dubbo.rpc.filter.CompatibleFilter^M
 16 timeout=org.apache.dubbo.rpc.filter.TimeoutFilter
 17 trace=org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter
 18 future=org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter
 19 monitor=org.apache.dubbo.monitor.support.MonitorFilter
  • --> org.apache.dubbo.common.extension.ExtensionLoader#loadDirectory
  • --> org.apache.dubbo.common.extension.ExtensionLoader#loadResource
  • --> org.apache.dubbo.common.extension.ExtensionLoader#loadClass
  • --> org.apache.dubbo.common.extension.ExtensionLoader#cacheAdaptiveClass // 该方法缓存所有 org.apache.dubbo.common.extension.Adaptive 注解的类,包含你自定的类。
  • // 小结: 上面完成了所有SPI类型相关的缓存。下面就是服务暴露或者引用时,如何抉择Filter 去留的流程了。
  • // 决定一个filter能否生效 org.apache.dubbo.common.extension.Activate#value 默认为空,需要一个抓手:org.apache.dubbo.common.extension.ExtensionLoader#isActive 该方法校验 value 为空的话就会默认生效;否则去url中匹配该value(url中的key),如果没有或者key对应的value为空则不能生效该filter。
  •  private boolean isActive(String[] keys, URL url) {
            if (keys.length == 0) {
                return true;
            }
            for (String key : keys) {
                for (Map.Entry<String, String> entry : url.getParameters().entrySet()) {
                    String k = entry.getKey();
                    String v = entry.getValue();
                    if ((k.equals(key) || k.endsWith("." + key))
                            && ConfigUtils.isNotEmpty(v)) {
                        return true;
                    }
                }
            }
            return false;
        }
  • // Filter总的选择流程:先加载默认Activate和自定义的,但排除xml或者注解中指定的。一般在org/apache/dubbo/dubbo/2.7.3/dubbo-2.7.3.jar!/META-INF/dubbo/internal包下定义好的。
  • 再加载xml中指定的filters; 此处一定要注意,如果优选在的加载自己定义的filter必须给filter Activate注解指定value值如下:
  • @Activate(group = {CONSUMER, PROVIDER}, order = 100, value = "commonxxFilter"),然后在配置文件或者xml中自行指定该Filter的Id ;;的确有点别扭????☠️
     
  • 【dubbo】 dubbo Filter 如何根据环境指定自己的Filters (其他SPI接口同理)
  • // 使用举例:
  • 如果注解中指定了value,则需要在url中出现该key并且指定value时才会被加到过滤链中。但是如果xml中指定,就会忽略此value值
  • 【dubbo】 dubbo Filter 如何根据环境指定自己的Filters (其他SPI接口同理)

3 最后总结:

  • 1 全局指定直接使用 就可以了,同时也可以对具体的service,reference进行覆盖;
  • 2 其他SPI接口可以做类似的配置;
  • 3 filter能否生效主要看org.apache.dubbo.common.extension.Activate 注解的value group等 具体匹配
  • 4 由此可以对不同的环境进行拦截,如果结合路由或者loadbalance SPI 也可以做业务上的自定义调用链路。

本文地址:https://blog.csdn.net/qfzhangwei/article/details/111033630

相关标签: 架构 dubbo