一、背景
1、企业级应用系统在运行的时候可能会有下面这些种类的错误/失败发生:
(1) 依赖组件挂了,可能是 db,可能是 mq,可能是 cache。
(2)依赖服务挂了,可能是别人给你提供的 http/rpc 服务挂了。
(3)可能是你的依赖方超时了。
(4)可能是调用方的参数有问题。
(5)可能是调用方的参数无法正确地通过校验。
(6)可能是用户的某种操作在业务逻辑上不合理性,不能够接着让他执行下去
(7)还可能是程序自身出错了,比如数组越界,把 null 当成了某种合法的数据结构等等。
上面这些情况都是有很大概率发生的,当这种情况发生的时候,如果用户向你反馈了问题,你要怎么进行跟踪呢?
2、互联网公司在系统内部出了点什么问题的时候,展现给用户的是什么?白屏、无任何响应、nginx 504 Gateway Timeout。用户都不知道这些是什么。
二、目标
1、用户角度
对于产品的用户来讲,希望的是无论任何情况下都要有一个明确的反馈,正常情况下自不用说。而特殊情况下,也应该看得到系统到底出了什么问题,用户网络不行了就告诉用户是网络问题,不要出现一堆莫名其妙的英文。在各种异常情况下,要保证用户能够恢复到正常使用中去。不要显示用户看不懂的任何信息。不要什么都不显示(白屏)。用户的想法会要求在服务端就有完善的错误兜底。而不是写完正常的业务逻辑就完事了。
2、研发角度
实际上就是要有调用链的错误存储逻辑,比如errors 应该是能够一路把上游的错误串下来,而不是直接只存储当前这一级出了什么问题。
错误码最大的好处大概就是能够按照错误码建立自己的业务错误字典,这个字典你甚至可以在客户端进行存储,当用户使用报错的时候可以直接弹出错误原因自查选项以及恢复建议。错误码对于用户和客服,客服和技术人员之间沟通也有很大的好处,至少在软件使用和技术方面上的沟通成本会下降很多。
当看到错误码或者错误信息的时候,能马上找到代码的位置就事半功倍。
三、如何存储
(1)所有错误消息都已经确定,可以写在程序里,用枚举比用全局常量更容易。
(2)错误消息不能固定,可能在应用过程中添加,保存在数据库中。专门写一套管理类来处理,用 HashTable 或者 HashMap 之类的方式来实现。
(3)把错误的key放在java的枚举里面,然后把错误的key和错误的信息的映射放在外部文件中,比如properties文件里。在运行时,根据错误枚举的key来实时从文件中取出错误文本就可以了,因为错误不是经常发生的,实时读取错误信息应该没有问题,当然也可以在程序启动时候把所有的错误信息读进来然后放到缓存里以提高性能。
四、针对公司具体项目设计错误编码的具体实现
1、统一设计目标
统一展示用户提示信息:编号“-网络异常,请联系相关人员处理!”
例如:x10101001-网络异常,请联系相关老师处理!
2、如何存储并获取错误信息
存储:在程序中使用枚举对错误编码进行存储。
定位:根据前端反馈的错误码去程序定义的枚举中查看并定位问题。
3、具体编码设计
第1位(固定,用x标识,没有特殊设计含义,只是方便存储)
第2位(错误提示级别,1为非系统bug,2为系统bug需要改代码)
第3-4位(顶级功能模块)
第5-6位(扩展子功能模块)
第7-9位(错误编码,从001开始,依次顺延)
实例:x10101001