记一次线上修复
上周五我们给服务器开发了新的功能, 单元测试都过了, 不过部署到测试服务器 的时候总是有问题. 百思不得其解, 只好逐步打印部署, 最终发现一个数据库函 数少处理了一个情况, 导致每次一个全新的请求都会失败. 而单元测试里的请求 总可以找到数据库原有的记录, 自然是无法检测出来. 不过这个单元测试的缺陷 我很清楚, 当时为了省去重新整理数据库记录而使用了一些小伎俩. 并未意识到 会出现覆盖问题. 另一方面在重构 Go 代码时, 对于非常常见的错误检查分支并 不在意, 以至于漏掉了一个关键情况, 从而酿出苦果.
教训是:
-
线上测试稳定复现问题而单元测试未出问题, 可以肯定是单元测试未能覆盖到某些重要的情形.
-
单元测试尽可能和实际使用场景一致. 如果不得不做一些妥协, 那么被mock掉的部分也要有相应的测试手段.
-
每次重构代码之后, 最好查看测试所覆盖的代码, 思考未被覆盖的代码的意图.
-
对于代码中所涉及到的各种可能的if/else分支, 哪怕是很简单或者并不常见, 也需要想好走到该分支的可能性.
然后测试服由测试同学确认无问题之后, 在周六中午上线到生产服务器. 之后就 来了大麻烦. 部署之后, 下午测试发现预期功能全部失败了. 我回来查看了数据 库, 发现我们使用的阿里云服务返回的结果不正确. 接着老板发现生产服务器上 提交给阿里的URL带有internal字样, 我们才意识到生产服务器和测试服务器上 配置的阿里云存储的EndPoint不同, 随后将其改正. 一直折腾到凌晨.
总结是:
-
测试服务器正常而生产服务器错误, 已经是很强烈的信号, 表明是服务器配置问题.
-
新功能最好在工作时间上线, 以便有时间观察和修改.
-
废弃和测试用代码及时删除, 减少阅读代码的障碍.
最后, 两次调试修改时波折不断, 主要是修改, 部署, 测试带来的效率问题. 需 要设想一个妥善的手段来将其自动化. 虽然我们已经有 CI 工具, 但是对于线上 环境的复现, 测试和修复还缺乏相应的经验和手段, 需要完善.
第一次线上修复, 呛得厉害, 身体上也吃不消, 必须避免.