切记一定要先执行业务逻辑再进行其他操作!
程序员的教训
问题现象
后台传来报警,充值平台余额不足,发现大量充值记录。
分析
先看一下代码:
发起http的post请求,然后将返回体显示,并用logs记入日志,之后,将订单提交成功/失败的结果填写入订单表
HttpResponse<String> response = Unirest.post(aaAgentConfig.getAgentUrl() + "/xxx.php/xxxxx/xxxxxx")
.header("Content-Type", "application/x-www-form-urlencoded")
.fields(paramMap2)
.field("sign", sign)
.contentType("application/x-www-form-urlencoded")
.asString();
System.out.println(response.getBody());
System.out.println(response.getStatus());
if(String.valueOf(response.getStatus()).equals("200")){
logs.add("提交订单成功"+response.getBody());
addFeeCharges2AaOrder(aaOrders.get(i),"1.已提交充值平台"+response.getBody()+aaAgentConfig.getAgentName()+aaAgentChooseConfig.getChargeName()+"id:"+aaAgentChooseConfig.getChargeId(),"1");
}else{
log.info("提交订单失败"+response.getStatus()+response.getBody());
logs.add("提交订单失败"+response.getStatus()+response.getBody());
addFeeCharges2AaOrder(aaOrders.get(i),"2.提交失败"+response.getStatus()+response.getBody()+aaAgentConfig.getAgentName()+aaAgentChooseConfig.getChargeName()+"id:"+aaAgentChooseConfig.getChargeId(),"2");
}
再看报错
原因是Logs.add会自动提取ip地址,但是定时任务没有请求来源,所以ip地址为空。
但是,在报错后,程序没有崩溃,而是直接终止此请求。但是请求发起后的业务逻辑没有执行!
也就是说,在每个定时任务中,都发现有这个订单,但是业务逻辑都没有执行,导致重复充值!
结论
由于用接口调试完程序,直接复制到定时任务当中,发布完就去吃饭了。导致事故发生。
补救
以下处理方法建议都做
- 在logs增加判断是否定时任务的函数
- 在getIPAddr()函数中增加结果为null的判断
- 在定时任务环境中使用专用日志增加函数
由于该充值操作可以撤回,所以赶紧找了充值平台管理员,执行撤回操作。未造成严重经济损失。
教训
- 一定要注意业务逻辑的紧密性,不要随便在业务逻辑里面随便插日志!尤其是带有IP地址获取日志这种有使用场景的操作。
- 不要蜜汁自信,程序发布直接上线,都不带测试的。
改之后的代码
业务逻辑:
System.out.println(response.getBody());
System.out.println(response.getStatus());
if(String.valueOf(response.getStatus()).equals("200")){
addFeeCharges2AaOrder(aaOrders.get(i),"1.已提交充值平台"+response.getBody()+aaAgentConfig.getAgentName()+aaAgentChooseConfig.getChargeName()+"id:"+aaAgentChooseConfig.getChargeId(),"1");
logs.add("提交订单成功"+response.getBody());
}else{
log.info("提交订单失败"+response.getStatus()+response.getBody());
addFeeCharges2AaOrder(aaOrders.get(i),"2.提交失败"+response.getStatus()+response.getBody()+aaAgentConfig.getAgentName()+aaAgentChooseConfig.getChargeName()+"id:"+aaAgentChooseConfig.getChargeId(),"2");
logs.add("提交订单失败"+response.getStatus()+response.getBody());
}
获取ip:
public static String getIpAddr() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 在定时任务等没有ip请求的情况下,调用获取ip地址,造成报错,解决此问题。
if(request==null){
return "127.0.0.2";
}
// 在定时任务等没有ip请求的情况下,调用获取ip地址,造成报错,解决此问题。-end
修改Logs.add
(这个就不放了)