可能一个系统要对接很多的渠道,每一个渠道都有自己的错误码表,如何实现加不同渠道的错误码都映射为本系统的错误码。
CREATE TABLE `respcode_ref` (
`channel_no` varchar(2) NOT NULL COMMENT '渠道错误码来源编号:00-本平台;01-支付宝;02-微信',
`channel_code` varchar(10) NOT NULL COMMENT '渠道错误码',
`platform_code` varchar(10) DEFAULT NULL COMMENT '平台错误码',
`platform_type` varchar(2) DEFAULT '04' COMMENT '平台码类型:00:未知异常的平台码类型;01-系统异常的平台码类型;02:xx业务相关;03:xx业务相关;04:xx业务相关',
`channel_msg` varchar(512) DEFAULT NULL COMMENT '渠道错误描述',
`platform_msg` varchar(512) DEFAULT NULL COMMENT '平台错误描述',
`ref_type` varchar(2) DEFAULT '01' COMMENT '映射方式:00:系统自动添加;01-管理员手动添加',
`ref_status` varchar(2) DEFAULT '02' COMMENT '映射状态(01-处理中,02-成功,03-失败)注;有些渠道的错误码可以直接关闭我方订单',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`channel_no`,`channel_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='渠道-平台码转化表';
码表需要包含的功能:
- 码表可动态扩展(即渠道新增错误码后我方可以感知并完成映射)。
- 本系统内的错误码也需要经过码表转换。
- 自身码和渠道码经过映射后要具有友好性与安全性(即不能暴露太明确消息,又不能暴露代码bug)。
- 映射后可以得到订单状态(有些渠道用不同码代表不同的状态。我们需要经过人工配置到表中,当渠道返回特定的码时我方可以据此关闭订单)。
- 对业务代码侵入要小。
- 不能太过依赖redis(多级缓存),没必要的流程不能影响主业务(异步线程)。
1. 错误码可动态扩展
一般对接渠道过程中,错误码是跟文档一同给予我们的(线下)。但是随着渠道的优化和升级的过程中渠道会增加很多错误码。
我希望系统可以动态感知这个过程。若码表中无法映射到该错误码。系统会返回给用户一个模糊
的错误描述。并且开启异步线程
将该渠道码登记到码表中。并且会通过邮件通知
运营人员登录运营后台完成码表的映射。
这个过程也可称为码表的自我进化。
2. 错误码的安全性和友好性
我们借助码表的目的就是对外统一的输出错误码。
比如:A渠道,1001-xx字段非法;B渠道,1005-字段不符合规定,等等。而经过码表映射后,统一返回0001-xx字段不合法。
而自身系统若抛出异常,需要经过码表映射吗?
我感觉是需要的!
- 对外展示的码要具有
友好性
(比如入库失败,实际上要返回系统出小差等...)。 - 对外展示的码要具有
安全性
(不能让客户可以根据我们的错误返回得到系统内部的处理逻辑),即返回的错误描述具有一定的模糊性。
对外暴露的码经过上述的处理,用户或上游系统可能不清楚问题的核心点出现在哪?会通过客服来询问异常原因。若是通过开发/运营人员去日志中搜索
,那么势必会加大人力成本。
一般在系统中使用try-catch
来处理异常。我们可以要求开发人员将真实的错误描述throw
出去。而后经过我们的码表转换后,得到对外暴露的码。并且真实码和对外暴露的码会同时入库。
例如:1001-插入xx表失败,转换为1001--系统繁忙,请联系客服进行处理;
1002-空指针异常(系统抛出的),转换为1002--系统异常,请联系客服进行处理;
这样的话,根据错误描述,客服人员可以精确定位到问题所在。而开发人员也可以精确处理bug。
上述过程也可以称为自身渠道化和运营可视化。
3. 码表获取订单状态
因为对接不同的渠道,每个渠道使用不同的特定错误码表示特定的状态。而我们根据收到的渠道号+错误码
就可以判定订单状态。是否是成功/失败/处理中。这点也是需要依赖开发人员在码表的配置。
4. 高效率
码表我们是在库中配置,但是不能依赖于数据库。故我们一般需要借助于分布式缓存(Redis),但是还是存在问题:(1)太过依赖Redis,Redis挂掉会导致整个系统不可用。(2)进程与Redis交互依旧存在网络开销。
所以我们需要借助进程内缓存。即实现多级缓存
。
多级缓存的实现:即DB-->Redis-->Map。这样的话,码表转换效率也有了保证。
当然多级缓存需要保证缓存的一致性。我们一般借助缓存失效时间
+Redis订阅发布
去解决。
其次,例如码表的动态扩展等,我们可以采取异步线程
的方式去执行,尽量不影响主线程的执行。
5. 低耦合
码表转换作为一个优化功能,最后不要要求开发人员在业务代码中加入转换代码。可以通过代理模式/适配器模式
或其他方式处理响应报文(比如响应报文一般为JSON格式,JSON一般使用FastJson去转换为对象。若是我们视适配
FastJson)。开发人员调用MyFastJson.xx()
方法转换对象时,在该方法中已经完成转换(渠道码—暴露码均放入Bean对象)。开发人员直接在外部操作Bean对象。
这样的话,在开发人员无感知的情况下,完成了码表转换。