结论
先把结论放最前面,可忽略后面的过程
- org.apache.dubbo.rpc.Filter与com.alibaba.dubbo.rpc.Filter没区别
- spring.dubbo.provider.filter: 无该配置,服务中的该配置是用于xml中配置provider的filter
- provider filter或service filter可具体给这个provider或service配置过滤器
- 如果想去掉某个filter,可在 provider filter或service filter配置的前面加
-
- 排序在filter类上定义,order越小,优先级越高
@Activate(group = { CommonConstants.PROVIDER }, order = -100)
- 优先级越高的filter
invoker.invoke(invocation)
前的越早执行,invoker.invoke(invocation)
后的越晚执行
配置
org.apache.dubbo.rpc.Filter
与com.alibaba.dubbo.rpc.Filter
配置
apiExceptionFilterV1=com.didichuxing.dd596.driver.car.biz.filter.ApiExceptionFilterV1
provider filter配置
<dubbo:provider registry="registry" group="${dubbo.group.default}" filter="-DidiErrorHandleFilter">
service filter配置
<dubbo:service
registry="registry" interface="com.didichuxing.dd596.driver.car.api.VehicleRemoteService" filter="apiExceptionFilter"
ref="vehicleRemoteService" version="1.0.0${dubbo.version.suffix.provider}" />
服务中配置的dubbo exception filter不生效
原因1
当不配置到service时,已存在优先级更低的过滤器ErrorHandleFilter,该过滤器优先级更低,故invoker.invoke(invocation)
后更先执行,后面再执行时,就不存在exception,所以ApiExceptionFilter不会执行
原因2
当不存在ErrorHandleFilter时,在ApiExceptionFilter中虽然改写了result,但是未清除exception信息,导致后面的ProviderExceptionFilter执行时,再次改写result
问题:为什么添加到service上就生效了
当把ApiExceptionFilter添加到service上时,虽然仍然没有调整优先级,但是会先执行其它的全局过滤器,最后执行该ApiExceptionFilter,而在执行ApiExceptionFilter时,改写了result,在打印日志的filter中会将改写后的打印出来(request_out),但是之后的error filter会重写,所以获取到的响应有问题
附1-测试过程
初始
-
- org.apache.dubbo.rpc.Filter中配置apiExceptionFilter
-
- com.alibaba.dubbo.rpc.Filter中配置apiExceptionFilterV2
-
- provider filter添加apiExceptionFilterV3
-
- service filter添加apiExceptionFilterV4
其中apiExceptionFilterV3、apiExceptionFilterV4均在
org.apache.dubbo.rpc.Filter
中配置
结果上述4个apiExceptionFilter均会执行
结论
所以3、4配置或不配置都不影响过滤器的执行
测试-
在3、4中配置时,前面加上-
v1、v2执行,v3、v4不执行,说明如果添加了过滤器,可在某个provider或service中排除
测试com.alibaba.dubbo.rpc.Filter
将apiExceptionFilterV3、apiExceptionFilterV4均放入 com.alibaba.dubbo.rpc.Filter
中
v1、v2执行
测试Activate
新增 v6、v7、v8
v6: 只添加@Activate(group = "provider", order = 6)注解
v7: 不添加注解,添加org.apache.dubbo.rpc.Filter
v8: 不添加注解,添加org.apache.dubbo.rpc.Filter及spring.dubbo.provider.filter
6、7、8均不会执行
测试不添加spring.dubbo.provider.filter
v9: 只添加@Activate(group = "provider", order = 9)注解,添加spring.dubbo.provider.filter
只执行v9并不会执行
测试只添加@Activate注解
v10: 只添加@Activate(group = "provider", order = 10)注解,service filter中添加
service filter中添加无论添加 ApiExceptionFilterV10还是apiExceptionFilterV10,服务均无法启动
附2-ApiExceptionFilter
@Activate(group = "provider")
public class ApiExceptionFilter implements Filter {
private static final ILog LOGGER = LogFactory.getLog(ApiExceptionFilter.class);
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Result result = invoker.invoke(invocation);
try {
// 处理异常
if (result != null && result.hasException()) {
Throwable e = result.getException();
if (e instanceof NullPointerException) {
LOGGER.error("api_exception||errMsg=java.lang.NullPointerException||e=",e);
} else if (e instanceof IllegalArgumentException) {
return buildResult(result,UserErrorEnum.PARAM_ERROR.getCode(), StringUtils.isNotEmpty(e.getMessage()) ? e.getMessage() : "Parameter invalid");
} else if (e instanceof CarBizException){
return buildResult(result,((CarBizException) e).getCode(), ((CarBizException) e).getMsg());
}else if (e instanceof RpcBizException) {
// 包装返回的errMsg
int code = ((RpcBizException) e).getCode();
String msg = ((RpcBizException) e).getMsg();
return buildResult(result,code, msg);
} else if (e instanceof RpcException) {
return buildResult(result,((RpcException) e).getCode(), e.getMessage());
} else if (e instanceof Exception) {
LOGGER.error("api_exception||e=",e);
return buildResult(result,UserErrorEnum.SYSTEM_ERROR.getCode(), UserErrorEnum.SYSTEM_ERROR.getDesc());
}
}
return result;
} catch (Exception e) {
LOGGER.error("api_exception_invoke_error||errMsg={}", e);
return result;
}
}
private Result buildResult(Result result,int code, String msg) {
RpcResult rpcResult = new RpcResult();
// 处理RPC错误
rpcResult.setCode(code);
rpcResult.setMsg(msg);
result.setValue(rpcResult);
return result;
}
}
待优化点
- 将优先级调到最高
@Activate(group = "provider",order = 100)
- 构造 result时,设置exception为null
private Result buildResult(Result result,int code, String msg) {
RpcResult rpcResult = new RpcResult();
// 处理RPC错误
rpcResult.setCode(code);
rpcResult.setMsg(msg);
result.setValue(rpcResult);
result.setException(null);
return result;
}