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.TripleProviderExceptionFiltertripleConsumerException=com.seezoon.dubbo.support.filter.TripleConsumerExceptionFilter
复制代码
扩展知识
如何做到全局异常处理呢,比如我们 provider 业务逻辑有参数验证错误,Sql 错误等。如果能像 spring 提供的@ContollerAdivce一样处理就方便了。
这里需要我们自定义类似异常 Advice 的功能,让所有错误都能变成 RpcException 携带我们错误码及错误信息。
@DubboAdvicepublic class DubboExceptionAdvice {
@DubboExceptionHandler({IllegalArgumentException.class}) public void illegalArgumentException(Exception e) { throw new RpcException(100, e.getMessage()); }}
复制代码
这块实现比较复杂,这块我们封装到我们企业级脚手架中,有兴趣的可以参考github
评论