Code-Box, born for error codes.
在业务开发中,经常会出现以下现象:
- xxx失败了,帮忙看看什么问题
- 怎么会出现这个错误
- 这个提示不友好,得改
- 错误信息,该前端处理,后端处理,还是中台处理?
- 多个服务之间错误码一致,错误内容不一致
- 。。。
基于以上,我就下定决心,想做一款错误码系统,解决以上问题。这个系统,我称它为Code-Box 码盒。
错误码,对于很多人而言就是一串数字,它关联了系统上的各种错误信息。
错误码带给我们的作用是什么?
- 告知我们哪个系统哪个模块出了问题;
- 告知我们具体是什么问题;
- 通过决策和话术转换回显合理的错误内容给用户。
- 对于服务间的调用,即针对技术人员
- 对于客户端的调用,即针对非技术人员
错误码设计原则是,尽可能做到简洁。故我将错误码分成两部分:系统码(前4位)+错误码(后4位)
系统码和错误码区间区间 需通过后台申请。
由于要区分错误码类型,我定义了指定的区间进行分配,剩下未分配的区间,待后续动态扩展
例如,我所在部门假设会有50个项目来开发,那么我可以申请区间为00010000-00500000的错误码。当然后续由于业务扩展,又增加了新的项目,亦可以重新申请新的错误码区间!
我考虑了两种场景,对内错误码API和开放错误码API。
基础的模型有:运营后台、错误码系统、错误码服务
贯彻“错误码无侵入”的理念,对内设计的领域模型,主要有业务系统—>错误码SDK<—>错误码内部API
我们仅需要将错误码API接口开放即可,并 提供一套错误码API文档
码盒项目基于Springboot + Spring cloud + Mysql搭建而成,项目架构比较简单。
接入业务系统,通过配置中心配置,开启错误码同步及检测功能,并支持开启周期性更新错误码,错误日志同步...
待定。。。
从上图看出,我这里区分了4个角色:项目负责人、产品、技术、用户
这是接入码盒的第一步
- 创建业务部门:根据部门信息,对应创建一条部门记录
- 创建业务系统:根据系统信息,对应创建一条系统记录,并自动生成一个系统码,4位组成
- 申请配置:这里不仅可以申请错误码区间,还可以申请域名,端口等,这样可以协同管理跨部门的信息
这是最简单的一种接入方式。技术人员在具体的业务项目中引入码箱SDK,并在资源文件下定义code.json,内容参考如下
[
{
"code": 101,
"message": "参数有误",
"detail": "请检查入参:必填参数是否为空,长度超出规定限制长度 或 是否不符合格式"
},
{
"code": 102,
"message": "系统繁忙",
"detail": "可能发生了网络或者系统异常,导致无法判定准确的转账结果。此时,商户不能直接当做转账成功或者失败处理,可以考虑采用相同的out_biz_no重发请求,或者通过调用“(alipay.fund.trans.order.query)”来查询该笔转账订单的最终状态"
},
{
"code": 103,
"message": "根据监管部门的要求,请补全您的身份信息解除限制",
"detail": "根据监管部门的要求,请补全您的身份信息解除限制"
}
]
常见的项目,会将错误码定义在枚举类中,增加了可读性,以及便于迭代。
这里针对此业务错误码枚举类,增加了自定义注解 @CodeBoxData
的支持,如下。当然有些项目错误码多,需要按业务进行区分,即有多个枚举类,也一样在每个枚举类上添加 @CodeBoxData
注解。
配置注解的目的,也是为了生成错误码信息到资源文件下的code.json文件中。
至于怎么生成,这里主要借鉴了lombok、mapstruct等的思路,它们基于注解处理器,给我们提供了很多丰富的功能。
在编译期间,码盒的注解处理器将会将枚举类的内容动态添加到code.json。接着等项目启动,SDK将会将生成的错误码同步到码盒系统。
码盒提供了针对产品经理的一个解决方案,在公司产品经理和开发人员经常有这样几个苦恼:
- 开发人员定义的错误信息太技术,导致涌出部分售后问题,引发产品不满:“这不是我设计的!”;
- 修改错误信息,必须改代码,重新发布,引发开发人员不满:“又来!”;
- 错误信息应该从哪里处理,前端?后端?中台?,引发开发人员疑惑:“是你,是你,还是你?”;
以上问题,在码盒上统统解决,当发现错误信息会带来售后问题而需要优化时,仅需要在码盒后台修改即可!
业务项目基于Springboot + Spring cloud 框架
https://github.com/qJerry/Code-Box
数据库配置、端口配置、注册中心配置
spring:
datasource:
hikari:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/code_box?characterEncoding=utf-8&serverTimezone=GMT%2B8
server:
port: 8501
eureka:
client:
service-url:
defaultZone: http://localhost:1002/eureka/
<dependencies>
<dependency>
<groupId>com.github.qJerry</groupId>
<artifactId>CodeBox-Sdk</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
在错误码枚举类上添加自定义注解,枚举类的参数参考如下。
注意:如上所说,错误码分为系统码(前4位)+错误码(后4位),在业务项目上,错误码无需考虑系统码,故在定义上只要定义后4位即可。
@Getter
@CodeBoxData
public enum BusinessCodeEnum {
// 设备:1000-1999
EQUIPMENT_NOT_EXIST(1000, "设备不存在", ""),
// 用户:2000-2499
USER_LOGIN_AGAIN(2000, "请重新登录", "当前缓存信息已过期,需要重新登录");
Integer code;
String message;
String detail;
BusinessCodeEnum(Integer code, String message, String detail) {
this.code = code;
this.message = message;
this.detail = detail;
}
}
code:
business:
id: 1 // 业务部门id
system:
id: 1 // 业务系统id
refresh:
open: false // 是否开启周期性任务
cron: 0 0/5 * * * ? // 调度周期
sync-log: true // 是否同步错误日志
在每个需要用到错误码的地方,直接调用SDK的 ResultVO.err()
输入具体的错误码即可,如下
public ResultVO getCode(String name) {
if(Strings.isNullOrEmpty(name) || ! name.equals("Jerry")) {
return ResultVO.err(10101L);
}
return ResultVO.suc();
}
当然,SDK也内置了全局异常处理器CodeBoxGlobalException
,直接传入错误码即可。
throw new CodeBoxGlobalException(code);
为了尽可能做到不侵入业务代码,我制作了一个SDK,并添加了自定义注解或者直接配置文件的形式进行接入
支持对于在业务错误码枚举类上添加了自定义注解的类,将在编译期间,将其拉取到资源文件下的code.json中,业务技术方无需手写code.json文件,只需添加注解,即可快速完成接入的一大步。
内部封装了一个错误码工具类,使用了ASM动态字节码功能,在项目启动期间和周期性刷新错误码期间,将会动态添加或更新错误码到SDK的错误码枚举类中,对外透明化,业务仅需提供一个错误码作为入参,即可获取详细的错误码内容。
出发点:
可能有些人包括我一开始会直接使用redis缓存来存放错误码信息。但从实际使用上看,错误码更多的是静态数据,一般不会去频繁改动,这时候放置于缓存就有点浪费资源了。故我在做自定义注解处理器的时候,就想到了使用动态字节码技术,在运行期间放置或修改错误码信息。
当在后台修改对应的错误码信息后,若开启了周期性刷新,则会定时同步最新数据到本地~~
可以配置是否要同步错误码日志到平台、配置接入码盒的方式、配置是否要定时更新后台同步的错误码信息等等
当配置了同步错误码日志到平台后,即可在后台查看具体的错误信息,并给出具体的解决方案。
已完成码盒服务、码盒SDK的开发
运营后台相关功能。