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