遗留问题,排雷会炸,不排也会炸!

本周一个故障,记录一下。

html

诸位知道,历史遗留代码,只要能运行,通常都不肯意去动的。 然而, 遗留问题就像雷区,排雷会炸,不排也会炸。 这不,本周一个电子卡券导出的雷,炸得我真是“面目全非”。前端

具体代码没必要细讲。 看官只需懂得:电子卡券导出是一个PHP后台任务,接收消息队列的导出消息来处理任务。 在捕获了一个异常以后,走到了异常处理分支。异常分支有句代码 logger->warn 。 这有何错 ? logger 并无 warn 方法 ! IDE 也提示的。 因而 PHP 报 fatal error ,直接退出了进程。 这样,导出任务进程没法启动,没法处理消息,队列阻塞,前端就一直显示报表正在生成中。性能

为何 logger 没有 warn 方法 , 却还明显地写着 logger->warn ,甚至历经两年都没有发现 ? 想必部分读者已经了然:由于写在异常捕获中。异常测试,是很容易被忽略的分支。测试

值得说起的是,logger 有个 warning 的方法。 然而,开发者习惯用 warn 而不是 warning ,而且 warn 是动词,warning 是名词。 打日志本应该用 warn 而非 warning 。 底层 API 设计者但愿用新的方式取代老的方式,也必须考虑到大多数开发者的惯用法。

设计

另外一个问题是: 电子卡券导出为何处理这么慢?日志

进一步阅读代码可知,电子卡券导出代码,里层居然对每个订单循环进行处理:访问 DB 获取卡券信息,调用用户 API 接口,调用重量级的订单详情接口。环环相扣,真是使人“拍案叫绝”啊!htm

为何会出现这种状况 ? 原来,为了方便,导出代码复用了列表代码。而列表代码只须要处理 20 个订单, 但导出代码却会处理数万订单。可想其性能能够低到地内心面去。推测, 可能当时修改列表代码的时候,并无注意到导出复用了列表代码,只是在列表代码里修改了,但同时导出的处理也影响到了,而修改者浑然不觉。blog

调用重量级的订单详情接口,也值得商榷。 列表与导出要显示的信息不过七八个,却要调用订单详情接口,获取近百个字段。真是为了一个轮胎,拖了一辆卡车。须知,这事并不鲜见。注意到,导出外层批量调用了一次新的批量详情接口,却不料里层为了订单列表又循环对每一个订单调用了老的订单详情接口,使人以泪洗面!接口

这里有三个启示:队列

  • 对于大量数据,循环调用单个接口,乃开发之忌。列表若是这么作,必定会有一天跪掉;导出若是这么作,要么会拉跨被调用的业务方,要么本身慢到比蜗牛还慢。
  • 内心要有全景图,能评估影响范围(极为重要!),否则,很容易由于一个改动影响到另外一个地方。此是开发常理。
  • 不要为了一个轮胎,拖一个卡车。不要轻率地复用一个大的业务模块。若是要复用,请通读这个业务模块,并保证复用的模块是轻量级的。

处理一个故障,能够折腾不少时间。好比 “趴坟”啊,开会啊,每个细小的地方,必定要分析得水落石出,使人心服口服,无言以对,—— 哪怕这坨代码不再会在线上运行。 有这时间,能够多去发现和思考系统中的潜伏着的问题,根治之。

PS: 无心看到历史上的今天,发了一篇“代码问题及对策” ,里面早已谈到了这些问题。 后人哀之而不鉴之,亦使后人复哀后人矣。

相关文章
相关标签/搜索