昨天,一个上线已久的供应链金融项目出现异常,经过一整天的排查,终于定位了两个问题的原因,并通过重启服务解决了其中的1个问题,另一个问题需要发起上线流程,通过上线才能解决。这两个问题,分别命名为【消失的字段】和【消失的消息】。在正式阐述问题之前,先描绘一下系统概况,以便读者更容易理解文中描述的问题排查逻辑,问题排查逻辑是这两篇文章的重点。
上图虚线框内是供应链金融项目的服务,包括:银行对接服务(bank-adapter)、贷前服务(preloan)、贷中服务(onloan)和贷后服务(postloan),bank-adapter服务属于外联服务,主要和银行进行对接。
橙色线条表示业务服务(贷前、贷中和贷后)通过银行对接服务bank-adapter向银行主动发起查询,包括查询:企业准入结果、授信结果、融资申请结果、放款结果和还款结果。
绿色线条表示银行主动通过银行对接服务bank-adapter向供应链金融平台推送消息,bank-adapter服务收到消息进行校验解码之后发送到消息队列MQ,业务服务(贷前、贷中和贷后)监听消息队列实时获取最新的推送消息,进行业务处理。
目前系统出现了两个问题,一个是业务服务主动请求融资申请结果,发现没有审批额度信息——【消失的字段】;另一个是贷中服务和贷后服务无法从消息队列获取最新的消息——【消失的消息】。
本文主要描述【消失的字段】问题以及问题排查过程,并给出问题解决方案。
一、问题描述
供应链金融平台用户通过页面操作发起融资申请结果查询,发现始终无法刷新列表的审批额度信息,同时页面没有报错提示信息。
二、问题排查(按照橙色服务请求路线进行排查)
1、前端页面响应数据查看。在用户当前操作页面,按F12打开浏览器调试窗口,点击【Network】tab,清空当前网络请求,再次执行融资申请结果查询操作,此时在浏览器调试窗口可以看到对应的网络请求,查看Response,可以看到后端接口返回的响应结果中确实没有审批额度信息。此时,可以将问题范围缩小到后端服务。
2、模拟前端请求。构造参数,通过POSTMAN对生产的融资申请结果查询接口发起请求,该接口由bank-adapter服务提供,返回结果显示如下:
1 | json复制代码{ |
疑问来了,明明bank-adapter接口返回了审批金额(对应字段为clamt)信息,为什么贷中服务返回给前端的结果却没有审批金额字段呢?返回结果从bank-adapter服务传递给onloan服务的过程中出现了什么问题?
3、查看bank-adapter和onloan服务的日志,因为从代码里对服务间调用的请求和响应记录了日志。通过日志发现,银行返回给bank-adapter服务的结果如下:
1 | json复制代码{ |
贷中服务onloan将从bank-adapter收到的响应结果输出如下:
1 | json复制代码{ |
通过对比上述两个结果,发现:驼峰形式命名的字段全部消失了!!!另外,通过第2步的结果与bank-adapter服务日志输入结果对比发现:bank-adapter服务接口最终输出的结果字段都被转为小写字段了,而且有字段名不一致的情况。 可以断定bank-adapter收到银行返回的结果之后,做了一些逻辑处理。接下来看代码!
4、打开bank-adapter服务融资申请结果查询结果的代码,发现最后将银行返回的数据构建为一个ApplyResultResp类型对象。
1 | ini复制代码@Data |
具体转换代码使用fastjson工具进行操作:
1 | ini复制代码ApplyResultResp applyResultResp = JSONObject.parseObject(jsonResultFromBank, ApplyResultResp.class); |
从上述代码来看,不应该出现银行返回结果与bank-adapter接口响应结果不一致的情况,大胆猜测:生产上的代码与本地代码不一致。于是,请运维工程师从生产环境将容器中运行的bank-adapter.jar包拉下来,通过反编译查看ApplyResultResp类的代码,发现果然!反编译显示该类的代码如下:
1 | ini复制代码public class ApplyResultResp { |
由此看出,生产环境bank-adapter服务将银行返回的结果字段全部转为了小写,然后onloan服务收到这些小写化之后的响应结果,通过BeanUtils.copyProperties方法构建响应对象,而onloan服务的响应对象字段也是驼峰形式的,所以构建过程中,驼峰形式字段信息全部丢失。
三、解决方案
将bank-adapter模块的本地代码重新部署上线,即可解决该问题。至于为什么生产上的代码与本地代码不一致,有可能是代码封板之后,本地修正了代码,但是忘记发布了。
本文转载自: 掘金