zoukankan      html  css  js  c++  java
  • Dubbo Filter机制概述

    https://blog.csdn.net/prestigeding/article/details/82085705

     从上文可知,在服务的调用或消费端发送请求命令中,Dubbo引入过滤器链机制来实现功能的包装(或扩展)。Dubbo很多功能,例如泛化调用、并发控制等都是基于Filter机制实现的,系统默认的Filter在/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter文件中定义,内容如下:

    echo=com.alibaba.dubbo.rpc.filter.EchoFilter
    generic=com.alibaba.dubbo.rpc.filter.GenericFilter
    genericimpl=com.alibaba.dubbo.rpc.filter.GenericImplFilter
    token=com.alibaba.dubbo.rpc.filter.TokenFilter
    accesslog=com.alibaba.dubbo.rpc.filter.AccessLogFilter
    activelimit=com.alibaba.dubbo.rpc.filter.ActiveLimitFilter
    classloader=com.alibaba.dubbo.rpc.filter.ClassLoaderFilter
    context=com.alibaba.dubbo.rpc.filter.ContextFilter
    consumercontext=com.alibaba.dubbo.rpc.filter.ConsumerContextFilter
    exception=com.alibaba.dubbo.rpc.filter.ExceptionFilter
    executelimit=com.alibaba.dubbo.rpc.filter.ExecuteLimitFilter
    deprecated=com.alibaba.dubbo.rpc.filter.DeprecatedFilter
    compatible=com.alibaba.dubbo.rpc.filter.CompatibleFilter
    timeout=com.alibaba.dubbo.rpc.filter.TimeoutFilter
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
       以其中一个来说明一下Filter的定义要素:

    /**
    * EchoInvokerFilter
    */
    @Activate(group = Constants.PROVIDER, order = -110000) // @2
    public class EchoFilter implements Filter { // @1

    @Override
    public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
    if (inv.getMethodName().equals(Constants.$ECHO) && inv.getArguments() != null && inv.getArguments().length == 1)
    return new RpcResult(inv.getArguments()[0]);
    return invoker.invoke(inv);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
       代码@1:实现com.alibaba.dubbo.rpc.Filter接口。
       代码@2:添加Activate,其注解含义如下:
       group: 所属组,String[],例如消费端、服务端。
       value String[],如果指定该值,只有当消费者或服务提供者URL中包含属性名为value的键值对,该过滤器才处于激活状态。
       before:String[],用于指定执行顺序,before指定的过滤器在该过滤器之前执行。
       after:string[],用于指定执行顺序,after指定的过滤器在该过滤器之后执行。
       order:用户指定顺序,值越小,越先执行。
       除了支持默认的过滤器外,Dubbo还支持自定义Filter,可以通过service.filter指定过滤器,多个用英文逗号隔开,其配置方法为:
       < dubbo:service ……>
          < dubbo:parameter key = “service.filter” value = “filter1,filer2,…”/>
       < /dubbo:service>
       当然,可以为所有服务提供者设置共用过滤器,其指定方法为:
       < dubbo:provider …>
          < dubbo:parameter key = “service.filter” value = “filter1,filer2,…”/>
       < /dubbo:provider>
       消费端自定义过滤器的key为reference.filter,其使用方法在< dubbo:reference/>标签或< dubbo:consumer/>标签下定义属性。
       关于自定义Filter的解析代码如下:
       ExtensionLoader#getActivateExtension

    public List<T> getActivateExtension(URL url, String key, String group) { // @1
    String value = url.getParameter(key); // @2
    return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group); // @3
    }
    1
    2
    3
    4
       代码@1:参数说明。
       URL url:服务提供者或服务消费者url。
       String key:过滤器属性key,服务提供者固定为:service.filter,服务消费者固定为reference.filter。
       String group:服务提供者或服务消费者。
       代码@2:从url中获取配置的自定义filter。
       代码@3:如果value不为空,则将字符串调用split转换为数组,然后调用getActivateExtension方法,获取符合条件的过滤器。
       ExtensionLoader#getActivateExtension

    public List<T> getActivateExtension(URL url, String[] values, String group) {
    List<T> exts = new ArrayList<T>();
    List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
    if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { // @1
    getExtensionClasses(); // @2
    for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {
    String name = entry.getKey();
    Activate activate = entry.getValue();
    if (isMatchGroup(group, activate.group())) { // @3
    T ext = getExtension(name);
    if (!names.contains(name)
    && !names.contains(Constants.REMOVE_VALUE_PREFIX + name) // @4
    && isActive(activate, url)) { // @5
    exts.add(ext);
    }
    }
    }
    Collections.sort(exts, ActivateComparator.COMPARATOR);
    }
    List<T> usrs = new ArrayList<T>();
    for (int i = 0; i < names.size(); i++) { // @6
    String name = names.get(i);
    if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX)
    && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) {
    if (Constants.DEFAULT_KEY.equals(name)) {
    if (!usrs.isEmpty()) {
    exts.addAll(0, usrs);
    usrs.clear();
    }
    } else {
    T ext = getExtension(name);
    usrs.add(ext);
    }
    }
    }
    if (!usrs.isEmpty()) {
    exts.addAll(usrs);
    }
    return exts;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
       代码@1:如果配置的service.filter或referecnce.filter包含了-default,表示禁用系统默认提供的一系列过滤器。
       代码@2:如果不禁用系统默认过滤器链,则首先加载所有默认过滤器。
       代码@3:根据group刷选出适配的过滤器。
       代码@4:也可以对单个filter进行禁用,其方法是-过滤器名称的方式。例如如想禁用AccessLogFilter,则可以通过-accesslog方式禁用。-key,key为/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.r
    pc.Filter中定义的key。
       代码@5:判断过滤器是否激活,其逻辑是如果Filter上的@Activate注解value值不为空,则需要判断url中是否包含键为value的属性对,存在则启用,不存在则不启用。
       代码@6:加载用户自定义的Filter,也即是service.filter或reference.filter指定的过滤器。
       综上所述,Dubbo提供了过滤器机制,在真实服务被调用前提供扩展点。Filter机制就简单介绍到这里了,从下文开始会重点分析Dubbo服务提供的核心Filter。
       如果需要自定过滤器,需要在自定的工程中META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter文件中注册。
       本文就介绍到这里了,从下篇开始将会根据Dubbo的功能特性来详细分析其实现过程,其本质都是各种Dubbo 过滤器器。
    ————————————————
    版权声明:本文为CSDN博主「唯有坚持不懈」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/prestigeding/article/details/82085705

  • 相关阅读:
    Maven打包时去掉项目版本号
    maven编译的时候排除junit测试类
    Redis与Zookeeper实现分布式锁的区别
    分布式锁(基于redis和zookeeper)详解
    解读阿里巴巴集团的“大中台、小前台”组织战略
    java高并发系列
    JAVA之Unsafe学习笔记
    测试用例之正交排列法
    测试用例之因果图/判定表
    测试用例之边界值法
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/12016465.html
Copyright © 2011-2022 走看看