開發函式計算的正確姿勢 —— 排查超時問題
寫不盡的 code,查不完的 bug
通常我們寫 bug,哦,不對,寫程式碼時總不會一帆風順,往往各種 bug 充斥其中,即使測試有較高的程式碼覆蓋率往往也會有漏網之魚。能寫出一些比較隱蔽或者看起來像 feature 的 bug,並且經過了測試、code review 等層層的考驗,最終 merge 到主幹,這也算的上是一種本事。
這次,我們討論的場景是,當你製造的 bug 被別人發現或者不小心把自己坑了,而不得不去 fix,且你自己也忘了這個 bug 是怎麼寫的了,在這種情況下,如何排查問題?
一氣呵成,bug 側漏
var request = require('request'); exports.handler = function(event, context, callback) { console.log("event: " + event); console.log('context: ', JSON.stringify(context)); const options = { url: '%E6%B3%B0%E5%B1%B1&need3HourForcast=0&needAlarm=0&needHourData=0&needIndex=0&needMoreDay=0', headers: { Authorization: 'APPCODE 5d9129e294fc4f518793ae9f9a15dbff' } } request(options, function (error, response, body) { if (error || response.statusCode != 200) { console.log("error " + error); return } console.log(body.day_weether); }); };
很簡單的一個 nodejs 函式,剛剛接觸函式計算往往會意氣風發的一口氣抒寫出這樣一段程式碼,通常是為了簡單測試一下函式的使用流程。但是釋出到上去後,卻出現了呼叫超時的問題。
大膽猜測,小心求證
首先,在無從下手的情況下,你大膽猜測如下:
-
函式入口寫錯了
-
程式碼中的邏輯有問題
-
函式計算服務有問題
為了排除其中的 3 選項,首先透過 fun local,在本地執行測試:
fun local invoke nodejs_timeout
得到結果:
可以看到,程式也被卡在這裡了。由此,可以排除掉 3 的可能性。
接著,可以透過加一些日誌,或者單步除錯來進一步縮小排查的範圍,這裡選用單步除錯,因為這種方法往往更簡單。
首先,利用 VSCode 在側邊欄下一個斷點:
然後使用以下命令將函式以除錯的方式執行起來(除錯基本用法 ,這裡不再過多闡述):
fun local invoke -d 3000 nodejs_timeout
然後單擊 VSCode 的開始除錯按鈕進行除錯:
可以看到,函式被正確的呼叫了,且進入到了入口函式。到此為止,可以排除掉 1 的可能性。
接下來,就要確認 2 可能性中存在的問題。
在 request 處的程式碼設定斷點,continue 到裡面,然後在 Local 可以看到執行到此處時的變數的值。
可以看到,http 請求返回的 resposne 的 statusCode 為 200,符合預期。body 也是有資料的,這個也符合預期。
把
body.weakday
放到 watch 裡面執行一下,看下結果。
這個就不是預期中的值了。
仔細看下 body 這個物件,發現其顯示格式不對,透過 typeof 將 body 的型別列印出來:
這貨竟然是個
string
!
剛想破口大罵,但一想這程式碼是自己寫的,趕緊閉嘴。
那就轉成 json 吧。
但轉完後,發現事情更不對了,day_weether 並不直接在 body 下,而是隱藏的很深。
而且名字不叫 day_weether,這裡有個拼寫錯誤。正確的寫法應該是:
JSON.parse(body).showapi_res_body.f1.day_weather
What the.... 髒話都到嘴邊了,但一想程式碼自己寫的,總不能罵自己吧,趕緊修吧。
把正確的表示式貼到 Watch 裡面,檢視,果然能夠取到正確的值:
驗證完畢後,將正確的值貼上到程式碼中,心想,總算解決了。
重新執行一下函式,發現果然能夠取到資料了:
但函式依舊卡在這裡,並沒有繼續往下走————超時的問題依舊存在!
現在,憤怒的心情已經沒有了,取而代之的是藍瘦,香菇。站起身,望望窗外,讓冷風肆虐你的臉龐。許久,心裡平靜一些了。
山窮水盡,柳暗花明
冷靜下來,理一理線索:
從剛才的除錯結果來看,函式已經執行,且獲得了正確的結果,但是函式卻沒有結束,直到超時。突然,一個隱約的答案在你身邊徘徊,你拼命想要抓住,來回踱步,驀地,像是出現了救命稻草一般,開啟了函式計算 Nodejs 的 文件 ,你用盡力氣擺動眼球,快速閱讀文件,並在心裡懇求那根救命稻草的出現。恍然間,你如同穿越了一道厚重的鐵門,身邊的光線突然由暗變亮,你被這明亮的光線刺的睜不開眼睛。但你知道,答案就在這刺眼的光芒裡。眼淚,沒能止住,順著你的臉龐緩慢地流了下來。終於,你鬆開了緊握的拳頭,彎下了一直挺直的腰板,眼淚鼻涕突然傾瀉而出,你————失聲痛哭。所有的委屈從內心經過喉嚨、鼻子、眼睛發洩出來,伴隨著這一陣陣漸漸衰弱的迴盪聲,遠去。
哭罷,擦乾眼淚,平復下自己的心情,將那一段你追尋許久的答案緩慢但卻有力的敲擊出來:
callback(null, JSON.parse(body).showapi_res_body.f1.day_weather);
終於,這段程式碼就如同你家叛逆的孩子,脫去叛逆的偽裝,顯現出它乖巧的樣子:
欲善其事,先利其器
經過這一次事件,你總結出三條經驗:
-
寫程式碼要耐心、細心,每一段程式碼都要經過思考。 一口氣將功能寫完,往往是看上去寫的快,但實際上會埋很多坑,坑到別人還好,往往不小心會把自己坑了。
-
要多讀文件。 使用語言,要讀語言文件,使用第三方庫,要讀庫的文件,使用產品,要讀產品文件。如果不仔細閱讀僅憑自己的猜測去寫,寫出的程式碼往往漏洞百出。男人千萬不要硬撐,別對自己這麼很。累了要休息,可以讀讀文件放鬆下。俗話說得好,磨刀不誤砍柴工!
-
Fun 工具的熟練使用重中之重。 在前兩點都沒做到的情況下,卻能最終將問題排查出來,Fun 工具功不可沒!但與之功勞成反比的是,對 Fun 工具的學習尤其是本地除錯功能,花的時間反而是最少的,如此巨大的收益比,使自己下定決心,一定要再花些時間,把 吃透!
總結完,你又用心的看著自己寫下的程式碼,就如同看向自己的孩子,寵溺、疼愛、氣憤各種心情夾雜在一起。突然,你一皺眉,呵斥道:這樣不對,異常的時候,也要返回!
於是,你糾正了程式碼的錯誤行為:
if (error || response.statusCode != 200) { console.log("error " + error); callback(error, null) ; }
就如同,訓斥完與人打架的孩子,看到孩子聽話了,你露出了欣慰的微笑。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31551794/viewspace-2285141/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 開發函式計算的正確姿勢 —— 爬蟲函式爬蟲
- 開發函式計算的正確姿勢——OCR 服務函式
- 開發函式計算的正確姿勢——執行 Selenium Java函式Java
- django開發時遇到問題的正確求助姿勢Django
- 開發函式計算的正確姿勢——使用 brotli 壓縮大檔案函式
- 開發函式計算的正確姿勢 —— 依賴安裝方法一覽函式
- 開發函式計算的正確姿勢———為 PHP 執行時新增自定義擴充套件函式PHP套件
- 開發函式計算的正確姿勢——使用互動模式安裝依賴函式模式
- BigDecimal 在資金計算時正確使用姿勢Decimal
- Python開發遊戲的正確姿勢Python開發遊戲
- 計算網路頻寬需求的正確姿勢
- 開啟Git的正確姿勢Git
- 學習軟體開發的正確姿勢
- 掌握Redis分散式鎖的正確姿勢Redis分散式
- 「分散式」實現分散式鎖的正確姿勢?!分散式
- Redis的正確使用姿勢Redis
- vue多頁面開發和打包的正確姿勢Vue
- 區塊鏈的正確開啟姿勢區塊鏈
- Git和GitHub的正確開啟姿勢Github
- Postman 正確使用姿勢Postman
- Homestead 開啟mongodb正確姿勢MongoDB
- 前後端協同開發,使用 GraphQL 正確的姿勢後端
- 這才是實現分散式鎖的正確姿勢!分散式
- git commit 的正確姿勢GitMIT
- 玩轉 Ceph 的正確姿勢
- laravel 使用 es 的正確姿勢Laravel
- java關流的正確姿勢Java
- 使用快取的正確姿勢快取
- Fragment commit 的正確姿勢FragmentMIT
- 開源專案翻譯正確姿勢
- 翻譯 | 新手開始學習程式設計的正確姿勢程式設計
- Goland 開啟一個專案的正確姿勢GoLand
- 原始碼|使用FutureTask的正確姿勢原始碼
- 相容iphone x劉海的正確姿勢iPhone
- npm run dev 的正確使用姿勢NPMdev
- 限制UITextField字數的正確姿勢UI
- 使用 Java 8 Optional 的正確姿勢Java
- 解鎖 Redis 鎖的正確姿勢Redis