遗留问题,排雷会炸,不排也会炸!
本周一個故障,記錄一下。
諸位知道,歷史遺留代碼,只要能運行,一般都不愿意去動的。 然而, 遺留問題就像雷區,排雷會炸,不排也會炸。 這不,本周一個電子卡券導出的雷,炸得我真是“面目全非”。
具體代碼不必細講。 看官只需懂得:電子卡券導出是一個PHP后臺任務,接收消息隊列的導出消息來處理任務。 在捕獲了一個異常之后,走到了異常處理分支。異常分支有句代碼 logger->warn 。 這有何錯 ? logger 并沒有 warn 方法 ! IDE 也提示的。 于是 PHP 報 fatal error ,直接退出了進程。 這樣,導出任務進程無法啟動,無法處理消息,隊列阻塞,前端就一直顯示報表正在生成中。
為什么 logger 沒有 warn 方法 , 卻還明顯地寫著 logger->warn ,甚至歷經兩年都沒有發現 ? 想必部分讀者已經了然:因為寫在異常捕獲中。異常測試,是很容易被忽略的分支。
值得提及的是,logger 有個 warning 的方法。 然而,開發者習慣用 warn 而不是 warning ,并且 warn 是動詞,warning 是名詞。 打日志本應該用 warn 而非 warning 。 底層 API 設計者希望用新的方式取代老的方式,也必須考慮到大多數開發者的慣用法。
另一個問題是: 電子卡券導出為什么處理這么慢?
進一步閱讀代碼可知,電子卡券導出代碼,里層竟然對每一個訂單循環進行處理:訪問 DB 獲取卡券信息,調用用戶 API 接口,調用重量級的訂單詳情接口。環環相扣,真是令人“拍案叫絕”啊!
為什么會出現這種情況 ? 原來,為了方便,導出代碼復用了列表代碼。而列表代碼只需要處理 20 個訂單, 但導出代碼卻會處理數萬訂單。可想其性能可以低到地心里面去。推測, 可能當時修改列表代碼的時候,并沒有注意到導出復用了列表代碼,只是在列表代碼里修改了,但同時導出的處理也影響到了,而修改者渾然不覺。
調用重量級的訂單詳情接口,也值得商榷。 列表與導出要顯示的信息不過七八個,卻要調用訂單詳情接口,獲取近百個字段。真是為了一個輪胎,拖了一輛卡車。須知,這事并不鮮見。注意到,導出外層批量調用了一次新的批量詳情接口,卻不料里層為了訂單列表又循環對每個訂單調用了老的訂單詳情接口,令人以淚洗面!
這里有三個啟示:
- 對于大量數據,循環調用單個接口,乃開發之忌。列表如果這么做,一定會有一天跪掉;導出如果這么做,要么會拉跨被調用的業務方,要么自己慢到比蝸牛還慢。
- 心里要有全景圖,能評估影響范圍(極為重要!),不然,很容易因為一個改動影響到另一個地方。此是開發常理。
- 不要為了一個輪胎,拖一個卡車。不要輕率地復用一個大的業務模塊。如果要復用,請通讀這個業務模塊,并保證復用的模塊是輕量級的。
處理一個故障,可以折騰很多時間。比如 “趴墳”啊,開會啊,每一個細小的地方,一定要分析得水落石出,令人心服口服,無言以對,—— 哪怕這坨代碼再也不會在線上運行。 有這時間,可以多去發現和思考系統中的潛伏著的問題,根治之。
PS: 無意看到歷史上的今天,發了一篇“代碼問題及對策” ,里面早已談到了這些問題。 后人哀之而不鑒之,亦使后人復哀后人矣。
轉載于:https://www.cnblogs.com/lovesqcc/p/11143831.html
總結
以上是生活随笔為你收集整理的遗留问题,排雷会炸,不排也会炸!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 找到bug的根源,问五次为什么
- 下一篇: Java——日期类