Dubbo Triple 异常处理
从 dubbo 协议切换到 triple 最大的不适应就是异常的处理,异常都成 RuntimeException。
社区有两种方向
个人意见
针对内网微服务,错误码一定要在协议里面体现,这样才方便做错误码监控。
官网讨论贴
issues-10353issues-8363Triple协议异常设计
实现原理
通过定义 provider 和 consumer 的异常filter来无感处理。
注:用户自定义 filter 默认在内置 filter 之后
provider filter
@Activate(group = {CommonConstants.PROVIDER})
public class TripleProviderExceptionFilter 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()) {
return;
}
Throwable exception = appResponse.getException();
if (exception instanceof RpcException) {
RpcException rpcException = (RpcException) exception;
appResponse.setAttachment("err-code", rpcException.getCode());
appResponse.setAttachment("err-msg", rpcException.getMessage());
} else {
appResponse.setAttachment("err-code", RpcException.UNKNOWN_EXCEPTION);
appResponse.setAttachment("err-msg", exception.getMessage());
}
}
@Override
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
}
}
复制代码
consumer filter 这样到消费者转变成 RpcException。
@Activate(group = {CommonConstants.CONSUMER})
public class TripleConsumerExceptionFilter 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()) {
return;
}
String code = appResponse.getAttachment("err-code");
String msg = appResponse.getAttachment("err-msg");
if (StringUtils.isNotEmpty(code)) {
appResponse.setException(new RpcException(Integer.parseInt(code), msg));
}
}
@Override
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
}
}
复制代码
添加扩展申明
src
|-main
|-resources
|-META-INF
|-dubbo
|-org.apache.dubbo.rpc.Filter
复制代码
org.apache.dubbo.rpc.Filter 中纯文本内容
tripleProviderException=com.seezoon.dubbo.support.filter.TripleProviderExceptionFilter
tripleConsumerException=com.seezoon.dubbo.support.filter.TripleConsumerExceptionFilter
复制代码
扩展知识
如何做到全局异常处理呢,比如我们 provider 业务逻辑有参数验证错误,Sql 错误等。如果能像 spring 提供的@ContollerAdivce
一样处理就方便了。
这里需要我们自定义类似异常 Advice 的功能,让所有错误都能变成 RpcException 携带我们错误码及错误信息。
@DubboAdvice
public class DubboExceptionAdvice {
@DubboExceptionHandler({IllegalArgumentException.class})
public void illegalArgumentException(Exception e) {
throw new RpcException(100, e.getMessage());
}
}
复制代码
这块实现比较复杂,这块我们封装到我们企业级脚手架中,有兴趣的可以参考github
评论