公司最近在做微服务改造的过程中,我们选取的是Apache Dubbo,并且定义了统一的返回值对象RpcResult。但是如果服务提供者端内部方法报错的话,对于消费者端来说就获取不到RpcResult了,如下图
现在想针对于Rpc调用也实现一个类似于使用spring-web的@ControllerAdvice与@ExceptionHandler来实现的全局异常处理器。经过查看Dubbo文档,可以使用Dubbo提供的Filter来实现,下将实现过程进行记录。
示例项目
结构
服务提供者接口实现
/**
* @author Bobby Cao
* @date 2022/03/31 15:03
*/
@DubboService
public class DemoServiceImpl implements DemoService {
@Override
public RpcResult<String> sayHello(String name) {
if (true) {
throw new RuntimeException("test RpcExceptionFilter");
}
RpcResult<String> result = new RpcResult<>();
result.setSuccess(Boolean.TRUE);
result.setMessage("success");
result.setData("hello " + name + "!");
return result;
}
}
创建RpcExceptionFilter全局异常处理器
实现参考与Dubbo内部自带的org.apache.dubbo.rpc.filter.ExceptionFilter
package cn.caofanqi.filter;
import cn.caofanqi.api.RpcResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.service.GenericService;
/**
* Rpc全局异常处理器
*
* 使用@Activate并指定group = CommonConstants.PROVIDER,使其只在服务提供者端生效
*
* @author Bobby Cao
* @date 2022/03/31 11:17
*/
@Slf4j
@Activate(group = CommonConstants.PROVIDER)
public class RpcExceptionFilter implements Filter, Filter.Listener {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
@Override
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
if (appResponse.hasException() && GenericService.class != invoker.getInterface()) {
Throwable exception = appResponse.getException();
RpcResult<Object> rpcResult = new RpcResult<>();
rpcResult.setSuccess(Boolean.FALSE);
rpcResult.setMessage(exception.getMessage());
appResponse.setValue(rpcResult);
appResponse.setException(null);
log.error("RpcExceptionFilter catch exception msg:{}", exception.getMessage(), exception);
}
}
@Override
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
}
}
META-INF/dubbo/org.apache.dubbo.rpc.Filter中添加自定义过滤器
测试
项目示例源码:
https://github.com/caofanqi/dubbo-global-exception-handler