Nodejs 線上服務穩定性保障體系

RosemarieAV 8年前發布 | 10K 次閱讀 Node.js Node.js 開發

本文會有條理的將我們團隊在穩定性保障方面做的一些事情與大家分享,文中著重強調“線上”服務的保障,盡量不會涉及開發過程中的話題,改天會就開發過程的質量保障另外介紹。另外,我們在此方面也并非完全成熟,大家可以作為參考,但也許并非最佳實踐,本文我會盡量講我們的解決問題的思路,而不是最終如何執行。

說到線上保障,我覺得主要是以下幾個問題需要解決(從前到后):

  1. 開發過程中,如何保障代碼質量?
  2. 發布前,如何及早提前發現潛在問題?
  3. 發布過程中,如何保障上線過程?
  4. 發布后,如何快速處理回滾?
  5. 線上故障之后,如何最短時間發現問題?
  6. 發現問題后,如何最快時間內定位問題并修復?

下面就這幾個問題分別剖析。

一. 開發過程中,如何保障代碼質量?

這一部分的話題,我不展開討論,每個話題都能講好幾天,關于如何正確的處理錯誤,上個月@王子亭 在我們公司主辦的杭州 NodeParty 上有過一個很詳細的話題,原文見: https://jysperm.me/2016/10/nodejs-error-handling/ 。另外兩個話題,以后有機會我會展開分享。

二. 發布前,如何及早提前發現潛在問題?

開發流程,對于每個公司來說可能因人而異,看產品性質和團隊組成。對于我們公司來說,測試工程師是比較多的,一般質量保證都是測試同學來做保障。在開發過程中需要在fix所有bug之后才能進入下一步狀態,通常是“預發布”,預發布的目的是驗證一些線上配置和數據的正確性,通常進入預發布已經很少產生bug,通常1天后即進入上線狀態。“灰度”是看產品情況,分層次向用戶分發新版本。

另外,在我們 Nodejs 團隊,每個需求在開發完成之后(合 develop 分支之前)或者 hotfix 合并 master 之前,都需要師兄做代碼 Review,代碼 Review 不是 Review 代碼寫的是否規范,因為我們已經有強制的 ESLint 限制,Review 主要是檢查技術方案是否有問題,把握代碼設計的思路等。這一點現在做的還是比較好的,每個 Review 都會產出很多交流,對于新人的成長也非常有幫助。不過代碼 Review 因人而異,如果條件不允許,不可強推,否則反而會影響產品進度或者產生形式感。

三. 發布過程中,如何保障上線過程?

  1. Gitflow 流程,團隊博客之前有過介紹: http://f2e.souche.com/blog/npm-assistor/ 文中介紹了我們的自動化 Tag 工具,和定制化的 Gitflow 流程。
  2. 發布前自動化保障,做了兩件事情,啟動并驗證應用無致命錯誤(crash),執行關鍵接口自動化功能測試,保障此次發布不會對線上產生致命影響。為什么需要這一步,因為我作為一個發布者,有時候很難把握住開發人員的代碼,但是發布動作只有我能做,那我如何做到心里有數?這個事情就非常重要了,這樣甚至我可以在不了解任何需求的情況下任意發布,至少,不會引起P0級別的BUG。
  3. 關于我們的發布過程,三個要點:A.分布式多機每臺機器開多個 Cluster,重啟過程中使用 PM2 的 gracefulReload 來重啟,應用代碼對此響應,將各種鏈接釋放將 express 的 server 釋放后重啟,此時才會去重啟下一個 Cluster,以此保障線上服務不會停機。B.發布腳本使用 Fabric ,上傳用 rsync,安裝依賴用內網 SNPM。C. 我們的線上應用不依賴機器環境,隨便開臺機器,發布上去就可以運行 ,PM2 和 Node 二進制包都是和應用以及 node_modules 打包在一起的,這個對于快速升級集群非常重要!

四. 發布后,如何快速處理回滾?

上線后,萬一出現問題,如何快速回滾?去找 Git 記錄,然后 Git reset ?恐怕來不及了,所以在每次發布后,需要給 Git 打 Tag,標記此次發布的內容,并且更改 Package.json 中應用的版本號,以及增加 changelog,我們將此過程標準化,直接做成一個命令行工具,這個工具在前面那篇文章中有介紹: http://f2e.souche.com/blog/npm-assistor/

回滾的操作很簡單,就是回滾到上一個 Tag,將此動作,寫成一個腳本,尋找上一個 tag 點的 hash,然后執行 git reset hash 即可回滾到本次發布前的 tag 點。

五. 線上故障之后,如何最短時間發現問題?

這部分內容較多,是我們工作的重點,關于日志記錄和報警,日志分級等實現,可以參見團隊博客之前的文章: http://f2e.souche.com/blog/ri-zhi-gui-fan-hua-yu-fen-xi-jian-kong/

具體上圖里都有表述,通過這一整套體系,我們可以被動的發現問題,并且第一時間得知,而不是通過用戶的反饋或者老大的鞭策才發現問題,通常等整個應用崩潰或者卡住的時候,一切都已經晚了,而這套監控系統,可以在問題剛剛有苗頭的時候就及早發現。

最近我們在著重做的是 圖中的定時任務調度和監控系統,因為之前的體系,對于獨立運行的定時任務不太友好,不太好監控,并且穩定保障也做得不夠好,另外調度也比較混亂,針對這個問題,正在開發一套調度監控系統,可以做到統一配置調度,然后監控定時任務的報錯,以及定時任務是否按照預期上報了健康狀態(因為定時任務很容易出現卡住或者超時的狀態),如果任務不健康,還要及時自動重啟此任務。目前正在 code review 階段,還沒有部署到線上。

六. 發現問題后,如何最快時間內定位問題并修復?

這里就不上思維導圖了,基本上就是上圖的那一整套方案中的一部分。我這里詳細描述下,我們如何通過日志快速定位的。

首先,所有 Error 級別以上的日志都會進 ELK,那這些 Error 都記錄了什么類型的錯誤呢?

  1. 業務代碼錯誤,這是比較特殊的,是開發者自己記錄的錯誤。根據此錯誤,可以在線上定位具體業務邏輯,一般記錄的時候會記錄錯誤棧+錯誤文件和行數+上下文信息,例如參數之類的數據。
  2. 全局通用錯誤,例如發起請求的錯誤,例如 express 的中間件錯誤,例如數據庫錯誤,緩存錯誤等,如果出現錯誤,會統一通過框架記錄到日志中。
  3. 最后一道門,uncaughtException 和 unhandledRejection ,用來記錄被忽略的可能導致應用 crash 的錯誤,例如直接 throw 出來的 Error 或者 語法錯誤等。對于 uncaughtException 我們的處理方式是捕獲,然后記錄日志,記錄完畢,吞掉。晚上對于此種處理方式頗有異議,但是作為一個線上服務,crash 是非常嚴重的。but 一定要記住,在測試環境千萬不要吞掉 uncaughtException,把錯誤暴露出來,并且直接 crash 掉,這樣才能在開發和測試階段排查出 crash 級別的錯誤。

以上記錄的錯誤日志,在 kibana 中很容易定位到 詳細的錯誤日志,快速分析原因。

如果你覺得還不夠,哪還有最后一道武器。利用一種請求跟蹤的方案,在進入一個請求之后生成一個 RequestId,講此請求記錄到日志平臺,然后在內部業務代碼報錯之后,能夠獲取到這個調用鏈條上最頂層的請求的 RequestId,以此日志,我們可以追蹤到導致報錯的這個請求的詳細信息!

小結

線上服務穩定性保障是一門大學問,上述講的只是一個基礎措施,在服務變得越來越龐大之后,其實整個架構都是在為穩定性健壯性服務,不過此文不想涉及太深,希望大家能夠看完此文后有一些感想,在自己公司的服務穩定性上有一些啟發,謝謝大家。

來自:http://f2e.souche.com/blog/nodejs-xian-shang-fu-wu-wen-ding-xing-bao-zhang-ti-xi/

 

 本文由用戶 RosemarieAV 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!