访问我的博客

目前计划对已有的单体项目进行组织架构拆分,调研了分布式系统中常用中间件 Dubbo 和 Spring Cloud,选择了 Dubbo,可以对当前现有项目进行平滑升级改造。但是一开始就遇到了麻烦,自定义异常在传递的过程中变成了 RuntimeException,统一异常处理 GlobalExceptionHandler 无法获取异常信息。

问题重现

项目进行统一异常处理,抽取了一个通用异常 ServiceException,此异常是非受检异常,即继承于 RuntimeException。调研时发现如果服务提供方即 provider 抛出了 ServiceException 异常,consumer 服务消费方就会收到一个 RuntimeException 异常,而 ServiceException 异常的内容被包含在了 RuntimeException 的异常堆栈中

[Request processing failed; nested exception is java.lang.RuntimeException: io.github.mosiki.common.exception.ServiceException: missing_required_parameters
io.github.mosiki.common.exception.ServiceException: missing_required_parameters
at io.github.mosiki.provider.HelloService.sayHello(HelloService.java:20)
at com.alibaba.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java)

而我的统一异常处理是这样的,只处理 ServiceException 以及 Exception,因此就无法获取到原始异常的信息了。

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler { @ExceptionHandler(ServiceException.class)
public Result handlerServiceException(ServiceException ex) {
return Result.failure(ex.getCode(), ex.getMessage());
} @ExceptionHandler({Exception.class})
public Result handlerException(Exception ex) {
log.error("发生未知异常:{}", ex);
return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器打了个小盹儿~请稍候再试");
}
}

访问接口将返回如下,异常中原有信息丢失。

上网搜索发现,这是因为 dubbo 的异常处理类 com.alibaba.dubbo.rpc.filter.ExceptionFilter 进行处理后的结果,Debug 之后确实如此,dubbo 在此进行了转换。

问题解决之道

现在我想要 provider 把自定义的异常原封不动的抛给 consumer 进行处理,于是有了如下思路:

  1. 禁用 provider 的 ExceptionFilter
  2. 让 GlobalExceptionHandler 处理 consumer 的异常

按照此思路做就很简单了,网上大多文章的办法都比较麻烦,有用 AOP 处理的,甚至还有让自己修改编译源码上传私服的-_-||,本文给出比较简便的方法,提供参考。

禁用provider的ExceptionFilter

修改 provider 的配置,我这里使用 yml 配置文件,其他类型如 xml/properties 也同理,设置 provider 的 filter 为 -exception,这样异常就不会被处理而是直接抛出了。

dubbo:
application:
name: provider
protocol:
name: dubbo
port: 20100
registry:
address: 127.0.0.1:2181
protocol: zookeeper
provider:
filter: -exception

GlobalExceptionHandler捕获ServiceException

只是禁用了 provider 的 ExceptionHandler 还不能完全达到我们的目的,访问接口,provider 抛出异常 consumer 正确接收为 ServiceException

[Request processing failed; nested exception is io.github.mosiki.common.exception.ServiceException: missing_required_parameters] with root cause

io.github.mosiki.common.exception.ServiceException: missing_required_parameters
at io.github.mosiki.provider.HelloService.sayHello(HelloService.java:20) ~[na:na]
at com.alibaba.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java) ~[na:na]

我们处理一下 GlobalExceptionHandler。

SpringBoot 主要这个启动类的位置和全局异常处理器的位置,一定要保证异常处理器在启动类的同级包或者在启动类的子包当中,否则异常处理器将不生效!

效果展示

以上两步完成后,重启服务,访问接口测试。

拿到了 provider 抛出的原始自定义异常,如此问题就解决了。

代码下载

参考

dubbo自定义异常传递信息丢失问题解决的更多相关文章

  1. JMeter中添加dubbo相关插件异常问题解决

    从网上下载了一个dubbo的插件,然后放到JMeter的/lib/ext目录下: 然后启动直接异常 发现启动不了,然后下载了一个全新的JMeter3.2将dubbo插件放到同样的目录,启动,没有问题: ...

  2. 找不到mysql.sock,mysql.sock丢失问题解决方法

    Can 't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock '(2) "; 是你的mysql ...

  3. MySQL远程连接丢失问题解决方法Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0

    最近远程连接mysql总是提示 Lost connection 很明显这是连接初始化阶段就丢失了连接的错误 其实问题很简单,都是MySQL的配置文件默认没有为远程连接配置好,只需要更改下MySQL的配 ...

  4. 关于c# SESSION丢失问题解决办法

    我们在用C#开发程序的时候经常会遇到Session很不稳定,老是数据丢失.下面就是Session数据丢失的解决办法希望对您有好处.1.在WEB.CONFIG文件中修改SESSION状态保存模式,如:& ...

  5. caffe.pb.h丢失问题解决方法

    https://blog.csdn.net/ThomasCai001/article/details/53940430 错误提示   fatal error: caffe/proto/caffe.pb ...

  6. AndroidKiller报.smali文件丢失问题解决(关闭Android Studio的Instant Run)

    第一节编写一个Android程序里我们生成了一个验证激活码的apk,当我们输入的激活码正确时才能注册成功,输入错误时注册失败. 现在我们想输入错误的激活码也能注册.我们用Android反编译工具进行反 ...

  7. Unity动态字体在手机上出现字体丢失问题解决

    在我们游戏的开发过程中,在部分手机上运行游戏的时候,出现了字体丢失的问题,出问题的手机似乎用的都是高通芯片. 使用的unity是4.2.0版本,ngui是3.4.9版本. 在unity的论坛及unit ...

  8. SWD下载调试填坑,SWD连接丢失问题解决

    野火SWD下载器,设置好以后,第一次下载成功,莫名其妙丢失连接,发现在复位状态可以连接(惊奇) 网络上搜索到把Boot0和Boot1置高,就可以把程序下载到RAM里, 能下载以后就好办了,把程序里SW ...

  9. MySql权限丢失问题解决

    参考文章 [mysql] root权限丢失恢复 完全菜鸟教程 今天用root账户登录到mysql后, show databases 命令返回的只有两个表, 然后使用 use database 命令提示 ...

随机推荐

  1. Linux学习--gdb调试

    一.gdb常用命令: 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或 ...

  2. Goldwave-5.7[逆向流程+算法分析]

    目标程序:Goldwave 5.7 分析工具: 1.OllyDbg 2.IDAPro 目的:用C语言写Goldwave-5.7的注册机. 0x0思路: 1.注册机准备: 功能:输入用户名后经过计算输出 ...

  3. PEM证书加密方法(python)

    1. 常见网络登录现在都使用了rsa加密,一般而言客户会提供模(mo)和指数(e). 2. 通过模和指数获取到证书PEM(方法见:https://www.cnblogs.com/luo30zhao/p ...

  4. [转]BSD系统正在死亡?一些安全研究人员这样认为

    摘要:在代码安全上被关注太少,漏洞没有被报告修补,FreeBSD.OpenBSD和NetBSD还能活下来吗? 在德国莱比齐的34c3网站上,IOActive的渗透测试主管Ilja von Sprund ...

  5. php签名认证

    一.概述 开年第一篇,该篇主要讲述了接口开发中,如何安全认证.如何用php签名认证. 二.说说历史 签名认证是什么?为什么要做签名认证?签名认证哪里会用到?no.no.no.....是不是,是不是,一 ...

  6. 可遇不可求的Question之MySql4.0前版本不支持union与批量SQL提交

    批量SQL提交 参考 21.2.6. Connector/NET Connection String Options Reference . Allow Batch true When true, m ...

  7. 基于fpga的vga学习(2)

    本次学习主要向配合basys2实行. 上次学习vga的rgb三个output都是1位的,但是我看了basys2的rgb分别是332位,这里让我卡顿了很久, 之后通过查资料才知道,rgb的不同大小表示的 ...

  8. shell丢弃信息

        1>/dev/null 2>&1 或 >/dev/null 2>&1 的含义及注意事项 > 表示重定向到哪 1表示stdout标准输出,输出到屏幕 ...

  9. mysql case when then else end 的写法

    select t.colum1,t.colum2 (case when t.colum1 = '' then '' t.when colum2 = '' then '' else '' end ) a ...

  10. 为什么delete指针后指针设为null(已解答)

    int *p;/*........*/delete p; p=null; 看代码的过程中,有这么一个疑问.删除了指针p,指针p既是不存在,怎么还能设置指针p为null呢?为什么还要设置为null呢? ...