记一次诡异的bug

前提:一份万年不变的代码,居然报了错

我们公司也算是个电商公司,网站自然支持支付宝和微信支付,支付网关完成后,使用一直没啥大问题,直到uat环境有一天突然基本不能支付,所有支付方式回调都失败,于是开始了漫漫bug长路。。。皱眉

1.看堆栈

root cause: caused by OptimisticLockingFailureException.....

乐观锁异常,是在根据id查询订单时报出来的,于是去看代码,没有发现代码上有啥问题,over哭

2.该bug并非每次都出,有很小的概率会成功,并且debug时不会抛异常,于是怀疑是多线程问题

由于uat环境最近网络不是很稳定,于是初步怀疑是支付宝或微信支付多次通知,多个线程同时查询(查询前有update hibernate托管的订单对象的操作),于是update--query交错执行,导致报错。

然后把线程池改成1,部署重启,依然报错。。。。over哭哭

3.看起来应该是多线程,但貌似又不是多线程问题,绞尽脑汁,看了两天的bug,无果而终。。。哭哭哭

4.寻找原因失败,那就对比吧,此时发现另外一个自测的test环境没有此问题。既然代码是一样的,那就只能怀疑是数据库了,虽然很牵强。。。

于是把test数据库copy到uat环境,重启服务器,bug神奇消失,好吧,虽然没找到原因,但总算解决了。

由于还要忙其他事,没那么多时间耗在这上面,所以勉强放过它吧,哦也~大笑

5.平静的度过了一周,直到一天下午,测试妹纸又跑来说粗大事啦支付不起啦。堆栈一样,错误一样,阴魂不散啊,这要怎么玩?!于是强烈怀疑运维对数据库做了什么(因为这段时间运维确实动过环境,不太稳定),so尝试甩锅给运维,直到。。。。

另一个妹纸跑来说了另一个问题,心想既然支付不了暂时解决不了,不如换个脑筋。于是开始看新问题,发现怎么特么数据库里一条记录存的id不对呢,根本和订单上的id不一样啊,就特么不知道是哪儿来的id,这什么鬼,彻底懵逼。。。哭哭哭哭

此时正好另一个娃听到了,说他遇到过这种情况,是因为我们的另一个服务在通知我们这边时,配置了多个不同端但url相同的记录,即不同端的通知全特么都会通知到我们这边,但我们这边不需要其他端的啊,我只要我们端的啊,你把其他端的数据发给我我能找到神马。。。于是屏蔽了其他端的通知,问题解决大笑,总算心情好点了,但特么支付问题还是要解决啊,测试都催了好久了,这么大的问题啊,继续抠脑袋。。。

抱着一丝侥幸心理,又支付了一把,居然神奇的成功了,不敢相信,又来了几发,没有异常,完美支付!难道和这个配置有关?!

于是又去梳理了一遍,发现:我们的服务在查询时,发现记录被更新了,但不是我们自己更新的,而是接收通知的服务更新的,而更新它的就是这些莫名配置出来的端发来的通知(其实根本不需要其他端啊,我们暂时只有一个端啊),所以乐观锁异常,这真是得来全不费工夫啊。。。

于是挨个去问,果然有人在支付出问题之前添加了好几个没用的通知地址配置,你手贱啊,没事添加没用的配置干啥啊?!我滴哥啊,既然找到原因,接下来就好办了:

1.接收通知的服务添加校验,丢弃非本端的通知

2.目前暂无配置多端的需求,配置模块添加唯一性校验,禁止添加多个端

看了2天的bug,硬是卵都没看出来,就这样解决了。。。。码农桑不起啊,心塞。。。。

不过排查bug也学到了很多东西,这也许也算码农的苦与乐吧

2017 fighting

猜你喜欢

转载自vinceall.iteye.com/blog/2350859