由Json⾃动转换造成精度丢失引发的⾎案……
两天!整整花了两天才搞定的⼀个⼩问题!
先简述⼀下问题:
写⼀个⼩系统,前端⽤Vue.js+axios,后端⽤php写的restful服务。axios负责进⾏与服务器端的api调⽤。订单ID是⽤php实现的snowflake算法。够简单吧?
问题:当从前端通过axios调⽤后端服务创建订单,创建成功后返回订单ID。这是够简单的逻辑吧?但狗⾎的啊,前端收到的订单ID与服务器端⽣成的订单ID竟然不相同,⽽且总是相差⼏位。可我的订单ID⽤的是字符串啊。。。。(想当然引发的问题。后⾯再说)
排查:
1、⾸先⽤postman进⾏服务器端的接⼝测试。相同的数据,通过postman创建订单正常,返回的订单ID也正常。
2、在⽹上了⼀下,怀疑是axios跨域⼆次请求造成的。(后来回头细想,这个是⽆厘头。为什么呢?如果是⼆次请求造成的,返回的订单ID不可能是如此的有规律,不会只相差固定的⼏位啊。snowflake算法
是加时间戳的,时间变化造成的ID变形是⾮常⼤的。)但还是排除⼆次请求的问题。⽹上有讲对于REQUEST_METHOD为OPTIONS的为⼆次请求,可以⼈家根本没有请求啊。甚⾄为了排查,连wireshark都⽤上了,抓包确认客户端确确实实只调⽤了⼀次!!
3、后来担⼼是不是axios异步提交造成的?(可明明已经排除重新提交了。但还是决定要试试)因为加了token机制。加了令牌后,通过postman可以提交,但axios就不能提交了,提⽰令牌丢失。
4、后来甚⾄都怀疑是不是服务器端使⽤的ID⽣成算法有问题。将php版本的snowflake算法换成了C语⾔版本,并做成了php扩展模式形式。但,涛声依旧!绝望了。
5、打开apache的dumpio模块,将respone写到⽇志。然后清清楚楚的看到respone中的id是正常的。
6、既然服务器端到最后输出都是正确的,那就先检查axios接到的原始输⼊是否正确。
7、在axios中注册transformResponse,显⽰原始数据。
transformResponse: [function(data) {
console.log(data);
return data;
}]
打开浏览器的F12,能看到终端输出(console.log)的内容,数据是正确的!!再次看解析后的值,⼜是错误的!那问题就在接到原始数据到获取解析值之间。终于缩⼩问题的定位范围了。
在axios的then函数中,最开始进⾏输出:
console.log(res.data);
值是正确的。添加解析后输出:
console.log(res.data);
var data = JSON.parse(res.data);
console.log(data);json检查
值是错误的
到此终于能定位是解析的时候出错了。但为什么解析会造成这个问题呢?
在终端上⽐较前后输出的时候,有⼀个细节引起了我的错误。
token: 6412591390922670080
token字段前后没有引号没有引号意味着整型
终于到问题了,服务器将id当成了长整型(token使⽤了与ID⽣成相同的算法函数)。长整型在客户端解析的时候造成了精度丢失。
回头看服务器的ID⽣成算法,原来使⽤的是RETURN_LONG,原来如此。
将算法中的Long型ID通过sprintf输出为String,然后输出。扩展模块更新,重启,问题解决
意外收获,将snowflake从php版本换成C语⾔版本,⽤php扩展模块加载后,性能提升⽐较明显。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论