前天有个产品要出版本,和我关系不太,一下班我就回家了。到家后接到老大的电话,客户端收到服务端推送多条相同的消息,让我赶紧到现网看看。我第一反应就是不相信代码会出问题,那个业务很简单。
匆忙登陆到服务器发现日志被删了,只好抓包。果不其然,服务器确实给客户端推送了多条相同的消息。通过跳板机,找到在内网编译遗留下来的代码,反复查看几 遍还是找不出问题在哪。这时候只好把debug日志打开,再重现一次。日志中多次向同一地址发送消息(其实前面的抓包已经反应出这个现象了),结合代码分 析,终于找到问题的所在。addr对象在循环外定义,而在循环内赋值,当在客户端对象中找不到地址时,addr不会被重置,addr仍然保存着上一个对象 的地址,从而导致了这次线上事故。
出问题的代码:
![](http://static.oschina.net/uploads/space/2013/0415/113403_v7Hc_725865.png)
抓包信息:
![](http://static.oschina.net/uploads/space/2013/0415/113627_eEfN_725865.png)
然而这个功能在上一次升级前并没有出现类似的问题,那导致这个问题的原因是什么呢?在一次review中,我看到addr定义在循环内,出于对性能的敏感,我把它挪到循环外,出于自信我并没有测试也没有理清业务流程就提交代码了。
review前的代码:
![](http://static.oschina.net/uploads/space/2013/0415/113436_7tlb_725865.png)
从这次事故中,我学到了很多东西。首先,不要盲目自信,再简单的代码也有可能出现bug;其次,对代码的每一处修改都要测试正确后才提交;最后,只有真正出现性能问题时,并且发现瓶颈在哪时,才着手去优化。