业务系统异常设计

本文讨论的前提是在捕获了异常的情况下进行的说明。

1、  直接使用原生异常。直接抛出 Exception 或者 RuntimeException。

  在业务代码层,直接抛出异常信息。这里不限定RuntimeException还是其他。

  好处是,简单方便直接。

  坏处是,部分调用方需要显式的抛出异常,且提示语不方便管理。

2、  项目包装RuntimeException。

  直接继承RuntimeException,做一些简单的封装,类似如下代码

  开发同学在使用时,直接new一个即可。总共两个构造方法可选,或者直接使用静态方法,生成包含对应detail的异常信息。其中常用的错误码、错误信息,都用一个静态类或者是枚举保存。我猜测大部分信息都采用的这种方式,而且这样的方式也满足一般的管理系统。

  好处是方便,有一定的标准。

  坏处是多个模块的开发者维护同一个枚举容易出现冲突,容易出现一个错误码被多次使用。

3、  多语言。

  如果公司业务发展较快,明天要进军泰国市场,后天要进军沙特阿拉伯市场,那就得在枚举全部新增一套提示语。虽然这样的改动不难,但没啥技术含量。

  所以我们将保存错误信息的枚举类进行改造,如下图

 

  重写toString方法

 

  这样就会带来问题,因为每次都需要新增加或者维护异常信息,都需要维护枚举类现有的几套语言。

  好处是方便,比较容易管理,支持多语言。

  坏处当然是浪费开发的时间,且一旦出现提示语不对,还需要重新发版,费时费力。

4、  可配置的异常提示信息。

  那既然现在的痛点是在维护上,我们何不考虑做成可配置?

  以将异常信息放在数据为例,先看两张表。

 

 

  此时,发生异常,若代码抛出异常,必须带上exception_code,异常处理service去包装异常信息,一方面返回异常信息给用户,一方面将异常信息入库。

  以springboot 为例

 

  异常信息的包装策略此处不展开,各位可以自己想想如何包装。

  这里好处就是异常信息可以随时调整,十分灵活,开发进行排查时也能有的放矢,不用去整个日志系统一遍一遍的去搜。

  坏处可能就是写的代码有点多,搞这么复杂一时半会也没啥用。

5、  分布式系统的异常信息传递。

  这里会与全链路日志追踪有交叉的地方。

  举个栗子,我在手机qq查看联系人性别:

  a)         打开手机qq(开始读取消息)

  b)         打开联系人列表(读取在线状态)

  c)         读取各种群消息(未收到的群消息)

  d)         搜索联系人(本地搜索+服务器搜索)

  e)         点开联系人详情页(获取用户通用基本信息、用户允许查看的隐私信息、用户背景图、qq会员系统、qq等级系统、各种钻、各种特权、头像挂件、个性签名、空间是否更新、最近常听)

  f)          查看用户性别

  而各个请求,可能又会去请求其他系统。

  任何一个系统调用失败,都可能会导致功能出现各种各样的问题。

  所以我们需要在异常信息中,传递一些必要信息,如 唯一请求编号、异常编码、异常机器ip等必要信息。假如调用链路是  S –> M -> Z -> E -> A -> H ,一旦E出现了异常并返回给Z,根据异常里面包含的信息,便能马上定位的机器,开始处理,而不是从链路的最开始一台一台机器去排查。

  最后补一个问题,自定义异常处理了,那非自定义异常该怎么办呢?

原文地址:https://www.cnblogs.com/brave-rocker/p/12643202.html