一、前言
前一段时间做了一个日志审计模块,其中会对HTTP调用、Dubbo接口之前做链路追踪,针对HTTP调用Dubbo接口、Dubbo接口中调用Dubbo接口的场景采用自定义Dubbo Filter(Provider/Consumer)的方式传递链路入口信息、操作用户、链路ID。其中牵扯到Dubbo RpcContext的使用,对着RpcContext以及遇到的坑,在下一篇文章中讨论;
二、自定义Filter
官方文档:https://dubbo.apache.org/zh/docsv2.7/dev/impls/filter/。
我们注意到在https://mvnrepository.com/artifact/org.apache.dubbo/dubbo中,org.apache.dubbo
组织下的dubbo版本最低只有2.7.0
;
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.0</version>
</dependency>
那么dubbo2.7.0以下的版本呢?在mvnrepository
中搜索dubbo,我们可以看到还存在一个com.alibaba
组织下的dubbo;
细想一下,dubbo最开始是没开源的;看来dubbo2.7.0之下的版本应该依赖都在com.alibaba
组织下:
谁闲着没事还会去看老版本呢?巧了老项目用dubbo2.6.X、dubbo2.5.X都太正常了;
博主就遇到了,业务方引入我的日志审计SDK说,说用不了;博主作为一个新程序员,学的基本都是新版本、新技术,也只有通过老项目才会去了解老版本;在此总结一下。
1、最新版本自定义Filter(dubbo2.7.X及以上版本)
1)实现Filter
package com.saint.dubbo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
/**
* @author Saint
*/
@Slf4j
@Activate(group = {CommonConstants.PROVIDER})
public class DubboProviderFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 服务端从dubbo上下文中取出traceContext信息
String jsonStr = null;
......
return invoker.invoke(invocation);
}
}
2)Filter实现类映射到Spring容器
在resources
目录下增加META-INF/dubbo/org.apache.dubbo.rpc.Filter
文件;
内容如下:
providerFilter=com.saint.dubbo.DubboProviderFilter
其中:
- providerFilter 为将要在dubbo配置文件或yml文件中配置的Filter名,想写啥写啥;
com.saint.dubbo.DubboProviderFilter
为我们自定义的Filter类;
假如我要写多个自定义的Filter呢?官方这里并没有说,很多博文也没说;其实再加一行就行。
providerFilter=com.saint.dubbo.DubboProviderFilter
consumerFilter=com.saint.dubbo.DubboConsumerFilter
3)Filter实现类关联到Dubbo Consumer / Provider
这里有两种方式(推荐使用第二种):
1> 在dubbo的xml配置文件中添加如下配置:
<dubbo:provider filter="providerFilter" />
<dubbo:consumer filter="consumerFilter" />
2> 在property/yaml配置文件中的添加如下配置:
dubbo:
consumer:
filter: consumerFilter
provider:
filter: providerFilter
如果针对一个consumer或provider有多个filter呢?以英文,隔开即可;
dubbo:
consumer:
filter: consumerFilter,userConsumerFilter
provider:
filter: providerFilter
2、未开源前的版本自定义Filter(dubbo2.6.X及以下版本)
Dubbo2.6.X及以下版本
与 Dubbo2.7.X及以上版本
在代码实现上的唯一区别点在于实现Filter的方式;Filter实现类映射到Spring容器的方式 和 Filter实现类关联到Dubbo Consumer / Provider的方式均一样。
1)实现Filter
package com.saint.dubbo;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
/**
* @author Saint
*/
@Slf4j
@Activate(group = {Constants.CONSUMER})
public class DubboProviderFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 服务端从dubbo上下文中取出traceContext信息
String jsonStr = null;
......
return invoker.invoke(invocation);
}
}
这里和2.7.X及以上版本的区别如下:
- 主要是引的包不一样;
Dubbo2.6.X及以下版本
使用的是com.alibaba.dubbo
包,而Dubbo2.7.X及以上版本
使用的是org.apache.dubbo
包; - 其次,指定@Activate的group属性时,常量类不一样;
Dubbo2.6.X及以下版本
使用Constants
常量类,Dubbo2.7.X及以上版本
使用CommonConstants
接口;
如下操作和Dubbo2.7.X一毛一样!!!
2)Filter实现类映射到Spring容器
在resources
目录下增加META-INF/dubbo/org.apache.dubbo.rpc.Filter
文件;
内容如下:
providerFilter=com.saint.dubbo.DubboProviderFilter
其中:
- providerFilter 为将要在dubbo配置文件或yml文件中配置的Filter名,想写啥写啥;
com.saint.dubbo.DubboProviderFilter
为我们自定义的Filter类;
假如我要写多个自定义的Filter呢?官方这里并没有说,很多博文也没说;其实再加一行就行。
providerFilter=com.saint.dubbo.DubboProviderFilter
consumerFilter=com.saint.dubbo.DubboConsumerFilter
3)Filter实现类关联到Dubbo Consumer / Provider
这里有两种方式(推荐使用第二种):
1> 在dubbo的xml配置文件中添加如下配置:
<dubbo:provider filter="providerFilter" />
<dubbo:consumer filter="consumerFilter" />
2> 在property/yaml配置文件中的添加如下配置:
dubbo:
consumer:
filter: consumerFilter
provider:
filter: providerFilter
如果针对一个consumer或provider有多个filter呢?以英文,隔开即可;
dubbo:
consumer:
filter: consumerFilter,userConsumerFilter
provider:
filter: providerFilter
三、总结
dubbo之所以有两种实现方式的根本原因,在于2018年2月份dubbo开源(阿里捐献给了Apache)后group由com.alibaba
变为了org.apache
;此外还有一些代码上的优化:比如 Dubbo2.6.X及以下版本常量采用Class类的静态常量维护,而Dubbo2.7.X及以上版本常量采用Interface接口中维护常量。
希望这边文章对同样维护老项目的兄弟有所帮助。