Dubbo -Filter篇

Dubbo -Filter篇

Scroll Down

Dubbo中Filter这个可以理解为我们在spirng-webmvc中的拦截器,对所有的http请求返回进行了拦截。只不过这里的拦截对象是消费者(Consumer)、提供者(Provider)

Filter的应用非常广泛,比如RpcContext、Monitor等都是使用拦截器实现的。

结合之前项目中的实战例子,先简单介绍一下如何使用吧~

场景:有些固定的标记参数需要在每个完整的业务流程中打印日志(类似于链路ID),那就意味着consumer每次调用都需要传这些参数到provider中。
为了不耦合业务,采用Filter对每个consumer的请求进行拦截,在请求前添加附加参数。

通过RpcContext上下文传递字段vid
consumer端的拦截器代码如下:

@Activate(group = CONSUMER)
public class WmdConsumerFilter implements Filter {

    @SneakyThrows
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {                   
        Map<String, String> map = new HashMap<>(2);
        map.put(Wmd.VID, ContextHandler.get(vid))); 
        RpcContext.getContext().setAttachments(map);
        return invoker.invoke(invocation);
    }
}

然后resources文件下新建文件,并添加内容
META-INF/dubbo/org.apache.dubbo.rpc.Filter:

xxx=com.xxx.XxxFilter

通过上面的配置之后,consumer每次调用provider接口的时候都会进入该拦截器,对这个字段设置到RpcContext上下文对象中。这样子provider使用的时候,只需要从RpcContext中取值即可。

原理简单解析:

  • 加载方式:在加载Extension的时候,Dubbo的SPI机制会根据META-INF/dubbo/org.apache.dubbo.rpc.Filter 这个文件加载相应的Filter实现类
  • 实现入口:在启动的时候会执行ProtocolFilterWrapper中的buildInvokerChain()方法,构建filter链
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.isEmpty()) {
            .......	

通过Filter的ExtendLoader实例获取其激活的filter列表,getActivateExtension逻辑分为两部分:
1.加载标注了Activate注解的filter列表
2.加载用户在spring配置文件中手动注入的filter列表

参考文章:
https://www.jianshu.com/p/f390bb88574d
https://www.jianshu.com/p/c5ebe3e08161