要想線上事故少,系統穩定性建設得搞好
1 前言
2 什么是系統穩定性
2.1 學術定義
2.2 工程實踐定義
2.3 量化指標定義
2.4 另一種角度的定義
3 為什么要進行穩定性建設
4 穩定性建設面臨的困難
4.1 資源投入難以找到平衡點
4.2 穩定性建設本身存在較高的復雜度和風險
5 怎么進行穩定性建設
5.1 達成穩定性建設資源投入共識
5.2 明確穩定性建設的目標
5.3 意識的培養
5.4 完備的生產規范
5.5 有效的監控預警
5.6 應急響應機制
5.7 加強日常巡檢和階段性復盤
6 后記
注:本文很多理論參考了得物技術公眾號的這篇文章商家域穩定性建設之原理探索,本文是基于這篇文章的思考及近半年團隊內對于穩定性建設的實踐總結而成。
1.前言
系統的穩定性建設是一個龐大的話題,其貫穿了產品研發整個流程:需求階段、研發階段、測試階段、上線階段、運維階段。從系統規模上看,小到單個系統,大到一個域的系統集,再大到支撐整個公司全業務的系統全集,都離不開系統穩定性建設。大家日常工作中可能會有一些關于系統穩定性的疑惑,比如經典三問“是什么、為什么、怎么做”,今天我從一個后端研發的視角,來和大家聊一聊系統穩定性建設的總結與思考。
2.什么是系統穩定性
聊系統穩定性前,得知道到底什么是系統穩定性,讓我們看看其定義。
2.1 學術定義
系統在指定邊界條件下維持其服務質量(QoS)的能力,包括在預期負載、異常輸入或部分組件失效時,依然能提供符合SLA約定的服務級別。
這個定義有些晦澀,大家可能有點不容易理解,來看一下工程實踐上的定義,從不同維度給出具體的說明。
2.2 工程實踐定義
服務持續性:在硬件故障、網絡抖動、突發流量等異常情況下保持服務可用。性能穩定性:99分位延遲不出現劇烈波動(如P99 < 500ms且抖動幅度<15%)。狀態可預期:系統行為符合"墨菲定律"預期(任何可能出錯的地方終將出錯,但系統有預設應對方案)。故障可降級:具備優雅退化(Graceful Degradation)能力,如購物車可獨立于推薦系統運行。
2.3 量化指標定義
圖片
SLA
:這里指可用性SLA,也就是常說的N個9,以常說的4個9為例,按全年時間計算,服務只允許4.3h不可用。MTBF
:Mean Time Between Failure,平均故障間隔時間=總運行時長/故障次數。指系統在相鄰兩次故障之間的平均正常運行時間,單位為小時(h)。它反映系統的可靠性,數值越高說明故障率越低、穩定性越強。MTTR
:Mean Time To Repair,平均修復時間=故障修復總時間/故障次數。指系統從故障發生到完全修復所需的平均時間,包括問題診斷、問題修復、測試驗證、上線驗證等全流程。數值越低,說明系統恢復能力越強。
從上面不同維度的定義可以知道,系統穩定性,追求的系統運行過程中少出問題,取決于兩個點,一個是系統風險,另一個是風險發生后的應對能力。也就是說,可以將穩定性簡化為一個公式:穩定性 = 系統風險(概率) * 風險應對能力。
圖片
2.4 另一種角度的定義
穩定性 = 系統風險(概率) * 風險應對能力。
咱們繼續拆解,對于系統風險,又分為固有風險和變更風險。固定風險一般指運維關注的網絡問題、服務器問題、容器環境相關問題;變更風險指隨著業務迭代對系統進行的功能上線、配置更新等人為操作引入的動態風險。運維團隊更多關注固有風險,研發技術團隊,更多關注變更風險部分。繼續拆解變更風險,可以得到:
變更風險=變更頻率 * 變更復雜度 * 變更爆炸半徑(影響范圍)變更頻率:變更次數越多,風險越大,一般和業務需求迭代頻率正相關。變更復雜度:包含業務本身的復雜度,代碼實現的復雜度,配置的復雜度。一般來說,復雜度越高,單次變更出問題的概率也越大。變更爆炸半徑:也叫變更影響范圍,表示發生問題后的影響面,直接影響實際的損失。
風險應對能力,分為風險發生前應對能力和風險發生后的應對能力。風險發生前:能不能發現,以及發現后能不能及時消除風險。風險發生后:能不能更快發現,以及發現后能不能及時修復。
風險處理能力 = 風險前置發現概率 * 前置風險處理 * 后置風險發現時長 * 風險應急處理
綜上能得出一個拆解后的穩定性公式:
穩定性 =(固有風險 + 變更頻率 * 變更復雜度 * 變更爆炸半徑)(風險前置發現概率 * 前置風險處理)(后置風險發現時長 * 應急效果)
這個公式將作為后續問題分析和實踐的理論基礎,所有的穩定性建設,都會圍繞著這些指標進行對應策略的制定。
3.為什么要進行穩定性建設
為什么系統穩定性如此重要呢,系統的穩定性是支撐業務發展的那個1,沒有這個1,后面再多的0,都將毫無意義。系統穩定性差,會帶來的影響有:直接的經濟損失:比如系統出現問題,導致訂單減少,金額出錯等,阿里前段時間出現的轉賬打8折問題,就造成了重大的直接經濟損失,這都是最直接的真金白銀損失。專業性會受到質疑:小到個人和團隊,大到公司,形象都會受到影響。對公司而言,大的事件可能變成輿論危機,對企業品牌形象帶來負面影響。相反,穩定性好,自然就會降低直接的經濟損失,也會傳遞出企業更專業的正面形象。除了這兩點,對于業務支撐的技術團隊,整體迭代效率會大大提高。為什么呢,因為系統穩定,花在堵洞上的精力就會大大降低,可以將更多精力投入到業務迭代上。
4.穩定性建設面臨的困難
對于技術團隊而言,每個人都知道系統穩定性的重要,但落地起來又非常難。有個詞叫“bug驅動”,意思是平時只關注支撐業務發展,很多問題暴露不出來,bug出現后,驅動技術人去關注代碼質量、流程規范等這些。為啥需要等bug出現呢,因為很多時候穩定性建設相關事項會被評定為“重要不緊急”,既然不緊急,就先緩緩再建設,緩到啥時候呢,緩到出現問題,然后bug驅動。究其核心原因,有以下方面:
4.1 資源投入難以找到平衡點
對于技術團隊而言,支撐業務迭代和進行穩定性建設的資源投入,很難找到平衡點。先說第一種情況,穩定性建設投入少,那系統質量肯定無法長期保證,高速支撐業務的同時,系統各種潛在風險隱患逐漸積累,到了臨界點,肯定會以bug或事故的形式出現在技術眼前。再說第二種情況,穩定性建設方向有充足的投入,短期內又很難用可量化的指標體現收益,不僅無法給業務證明其價值,甚至技術內部,短期都很難看出明顯效果。業務體感上只會覺得迭代速度慢了,他們在想,為什么不能更快的進行迭代上線呢,此時在項目優先級及排期上,就很難說服業務,業務出于壓力,肯定會將業務迭代優先級提高,壓力自然就會透傳到技術團隊。
4.2 穩定性建設本身存在較高的復雜度和風險
根據第一部分的公式可知,穩定性建設核心是識別風險、治理風險、預防風險,對于這每一部分,都不簡單。
4.2.1 存量風險識別的難度
如果靠上文說到的“bug驅動”當然也是一種識別風險的辦法,只是比較滯后,不符合穩定性建設預期。為了能防范于未然,需要主動去發現系統的風險,并想辦法解除風險。前面說了,穩定性建設覆蓋的系統范圍可大可小,想要評估出其中的潛在風險,這就涉及對全范圍系統代碼和業務的梳理,工作量和難度可想而知。
4.2.2 風險治理的難度
比如說現在風險已經識別出來了,進入到了第二步治理,也有困難,比如:1.資源問題:評估風險治理成本為一個月工期,能否給到正常的排期。2.引入風險:治理過程中,怎么保證不給系統引入新的問題。很多時候,系統的狀態其實和風雨中的危房差不多,而風險治理,不是簡簡單單在旁邊建一套新的,人搬過去就行,而是需要在維持房屋不倒的情況下,逐漸把房子各個地方修一遍,這個過程稍有不慎,可能就會砸到承重墻,后果就是房屋塌了。為了維修房子結果把房子弄塌了,這是不行的。3.治理執行:本身執行治理方案時也會有難度,比如常說的技術債,對于一套業務迭代多個版本,代碼經手N個研發之手的系統而言,不同的代碼風格以及大量為了解決短時問題而寫的if充斥在整個系統中,對于這樣的系統,給出一套合理的治理方案本身就很難。
4.2.3 增量風險預防的難度
增量風險主要來源于系統的變更,最主要的場景就是業務需求的迭代和技術側的系統優化。1.發生變更時,各方理解是否能達成一致,比如研發、測試和產品,對于變更的理解如果不一致,就會引入新風險。2.變更方案是否可控,如果保證方案最終能和預期一致,如果不一致,就會引入新風險。3.人員的可靠性,前兩步都一致了,但是研發在開發時粗心,代碼寫法上有問題,測試在驗證時粗心,剛好跳過了這條case,就會引入新風險。
5.怎么進行穩定性建設
上面列舉了系統穩定性建設的種種困難,前面說過,系統穩定性建設本身是一件重要的事,所以不管有多少困難,該建設還是需要建設的,那么面對這種種困難,如何進行穩定性建設呢?介紹建設具體方案前,先討論一個問題,系統穩定性建設到底建設的什么?
通過第一節的公式可以將穩定性建設分為三個方向,然后根據每個方向的具體影響因素指標,可以找到對應的建設思路。
圖片
5.1 達成穩定性建設資源投入共識
從上面的分析可知,系統穩定性建設排在第一位的困難是資源問題,那么想解決穩定性建設問題,首先技術內部要對系統穩定性建設投入多少資源達成一致,比如占團隊總工作量的多大百分比。這個百分比,不同的團隊不同的業務階段,都可能不一樣,需要針對本團隊業務的重要性、發展階段、風險情況進行綜合評估,確定穩定性建設在本團隊中的重要程度,依據這個重要程度逐漸調整這個投入占比值。
現實中,很多業務開發團隊,對于這個大前提是沒有共識的,就是既沒有相關資源的投入又想要系統穩定的結果,這個是不合理的。比如經常會遇到研發吐槽,技術設計方案、代碼CR不給時間,為了上線deadline,極致壓縮開發、測試排期,然后又要保證上線質量,這本質上是沖突的。
沒有資源投入,一切都是空中樓閣。系統穩定性建設的投入共識,研發內部達成共識后,還要和業務團隊充分溝通,取得他們的共識,在需求迭代速度和系統穩定性建設的資源分配上,共同探索一個合理的平衡點。
5.2 明確穩定性建設的目標
穩定性建設的目標,不同的階段可能不同,選取的考量指標也可能動態變化,比如年度技術三級事故不能高于M個,月度技術online問題不超過N個,再或者直接用系統4個9作為考量指標,都可以。明確了目標后,需要根據大目標拆解為階段性的小目標,以及根據目標制定出切實可行的落地方案。
結合穩定性建設思路思維導圖會發現,其最終建設思路落地取決于“人”和“機制”兩個方面,人去落地相關事項,機制用于保障和托底落地效果。接下來咱們看看各個思路如何具體的進行落地。
5.3 意識的培養
前面介紹提到系統穩定性建設依賴的是人來執行,人員的主觀意識決定了建設的落地難度和最終效果。這里主要包含三個方面:認知、意愿和能力。1.認知:團隊成員是否充分理解系統穩定性的重要。實踐建議就是,平時周期性提醒,典型問題重點強調,嚴重問題復盤總結,來逐漸加強大家對于穩定性重要性的認知。2.意愿:團隊成員是否花時間和精力去評估和解決穩定性風險(前提是有資源分配的情況下)。評估穩定性風險需要深入細致的梳理系統代碼邏輯業務流程等,對耐心、細心都是考驗,有時候可能覺得麻煩就簡化或者不做了,就會帶來潛在風險。實踐建議:對表現好的,激勵當榜樣,對表現不好的,一方面制定適當的懲罰措施,另一方面階段性的用二次檢查機制托底,降低風險。3.能力:團隊成員是否能識別風險并找到解決方案。在認知和意愿沒問題的情況下,這部分屬于人員個人能力的提升范疇,方式方法很多。比如組內相互分享學習,遇到問題請教其他同學等,都可以。
5.4 完備的生產規范
一次系統變更(業務需求迭代或技術優化)一般包含:需求評審、技術方案評審、編碼自測、用例評審、測試、CR、驗收、上線、線上驗證等環節。在實際項目推進過程中,嚴格執行項目流程規范需要投入的時間可能會更多,時間成本上考慮,可能會根據項目規模、特征等因素對流程環節進行一定程度的精簡。從結果上看,有時候項目也沒出什么問題,久而久之,很多人會覺得流程規范價值不大,會降低整體效率。其實不然,項目流程規范是保障系統穩定性的重要措施。每一個環節都有對應的執行規范,下面著重介紹和研發密切相關的幾個環節。
5.4.1 技術方案評審
技術方案評審環節分兩個方向,一個是是否進行了技術方案評審,第二個是技術設計和評審的質量。1.嚴格執行技術方案評審:對于開發周期大于N(根據不同團隊對流程要求的實際情況定,我們團隊是3人天)人天的項目,盡量有技術方案設計及評審環節,低于N人天的,可以根據復雜度、變更影響范圍等評估是否需要。
很多團隊只有那種大型項目,才會有詳細的方案設計和評審,對于普通周級別的迭代,需求評審完后,研發簡單梳理一下上下文,就直接拉分支進入開發階段。這種做法對于某些特定情況有deadline上線日期的中小項目,可以這么做,但一直這樣不重視技術方案設計,隨著時間的積累,可能就會引入穩定性風險。2.評審關注點主次分明:技術方案的重點要放在架構的合理性、可擴展性,系統的高性能高可用這些方向上,而不僅僅是實現業務訴求需要的表和接口設計。模塊最終的研發人,既需要關注宏觀層面的架構合理性又需要關注業務實現中的相關細節,對于參與評審的其他人,更重點的關注點需要放到架構合理性、擴展性這些宏觀層面的項上。3.參與人要求:關于參與技術評審的人是有要求和限制的,對本次變更模塊以及關聯模塊比較熟悉的研發人員,盡量參加把關,能輔助更好的評估變更風險影響范圍。4.關注點清單:對于技術評審,需要有沉淀下來的關注點清單列表,輔助評審參與人提出通用性的相關問題。對于業務研發而言,系統變更遇到的絕大部分問題,都是重復問題,也就是說業內其實有通用思路和解決方案的。哪些是和業務無關的具有通用屬性的關注點呢,比如:接口的限流、熔斷、降級、超時、重試、版本兼容,為降低變更影響范圍的隔離(環境隔離、數據隔離、核心業務隔離、讀寫隔離、線程池隔離)等,這些關注點就需要在技術評審階段重點關注。
5.4.2 代碼Review階段
研發環節,CR是保障穩定性的重要措施。這個環節該如何保證質量呢,有如下建議:1.不CR不上線:不經過Review的代碼不要上線,這是行業無數線上事故教訓后得出的建議,大家一定不要心存僥幸。這個可以通過流程上的規范限制進行強約束,比如我們的發布平臺可以設置上線前必須CR,也可以根據系統設置定向CR的人,否則不能進入到沙箱部署。2.代碼風格統一:要有團隊自己的整體代碼風格,統一一套編碼規范,這樣可以極大的提高CR效率。3.善用工具:善用工具發現代碼中的基本問題,比如用掃描工具發現代碼中潛在的NPE,工具比肉眼強無數倍。比如我們的發布平臺就集成了Sonar
掃描功能,壞味道和bug不修復完是不允許部署沙箱的。4.不過度關注細節:CR過程不要陷入細節,關注整體風格和寫法,以及性能、安全等通用關注項。對于很多參與CR的人而言,短時間內需要了解業務需求上下文細節,然后判斷代碼實現是否正確,這難度是很大的,所以大部分場景CR的是代碼基礎風格和通用問題。5.時長限制:控制單次CR時長,盡量不超過2小時,否則后半程大家精力容易分散,難以發現問題,降低整體CR質量。6.端正CR心態:先要明確CR的目的是為了找出代碼存在的隱患降低系統風險。如果作為被CR的人,放平心態,CR是一個很好的學習機會,發現不足及時學習,不要在CR時極力證明這種寫法也沒問題,偏離主題。作為主CR的人,也不要以挑刺和為難的心態去CR,不是為了證明誰強誰弱,只討論方案和實現的合理性就可以了。
5.4.3 上線階段
上線過程是線上問題爆發的高發期,為什么呢,這個過程涉及系統部署,數據更新,配置變更,以及變更過程中中間態的問題,任何一個環節出錯,可能整個上線就失敗了。一般上線需要做到三個點:可監控,可灰度,可回滾。1.可監控:上線過程中相關指標的監控,包括業務指標和技術指標,比如訂單量在上線期間是否有大的波動,接口可用率是否下降了,CPU、磁盤、網絡、異常日志這些是否正常等。這個每個公司都有自己的監控平臺,我們有很完善的監控系統Grafana
平臺,上線過程就需要觀察相關指標,比如:業務指標變化情況:
圖片
異常日志情況:
圖片
2.可灰度:灰度主要是為了降低變更影響范圍,一旦出問題,也可以將問題限定在可控范圍。灰度可以從技術維度進行:機器、機房、區域等維度;也可以從業務維度進行:按用戶、按商家、按品類等。3.可回滾:發現問題及時止損最快的方式就是回滾。回滾有兩種類型:代碼回滾和數據回滾。代碼回滾可以通過開關控制或者部署上一個版本的代碼實現。數據回滾指上線過程中,產生了中間態的臟數據,需要將數據回滾到正確狀態。
總結一下就是,灰度上線,上的過程眼睛緊盯各項指標是否有異常,發現問題,先回滾止損,再定位及修復問題。
如果系統順利上線,就進入到了風險后置處理環節,這個階段主要包括:發現問題、響應問題、解決問題、復盤問題四個部分。這個階段,除了復盤問題外,其他三個環節都和時效性強關聯,發現問題、響應問題、解決問題的快慢,都直接影響系統穩定性,慢就可能將影響和損失擴大。
5.5 有效的監控預警
業務反饋問題是發現問題的一種途徑,但如果等到業務反饋,時效性就非常滯后了,對用戶已經產生了影響,這是技術不愿意看到的。監控預警核心作用是為了及時發現風險,將風險影響范圍降低。針對監控預警,有這些建議:1.預警要全而精。全指的是對于核心業務的核心節點,都需要有相關監控預警,不能遺漏,指標分為技術指標和業務指標。精是指監控預警不是越多越好,預警過多很可能造成預警噪音,對產生真正影響的預警產生干擾。2.善用各種監控預警工具。實際工作中發現,很多必要的監控缺失,這樣的話,系統屬于無看管狀態,感知問題自然會很滯后。3.核心業務定向監控。在監控工具不能滿足訴求的情況下,要自主開發監控小工具,比如業務數據校對監控預警這種,監控平臺系統層面很難有定制化的功能。
我們團隊內部關于監控屬于兩者結合,有平臺工具監控,這一類比如系統層面的日志、網絡、數據庫、線程池、接口響應率等。也有自定義的業務監控,針對特定業務指標進行的監控。預警方式多樣:郵件、企業微信、短信。
任務執行異常監控預警
圖片
業務操作異常預警
圖片
服務間接口調用監控預警
圖片
error日志及慢sql監控預警
圖片
特定業務數據監控預警
圖片
5.6 應急響應機制
對于線上問題一般有三種來源:自主發現、業務反饋、監控預警。不管哪一種渠道發現的線上問題,都需要有一套響應機制來應對,核心就是降低影響和損失。出現問題該如何響應呢,提供以下建議:1.響應要及時:第一時間關注并推進問題解決,要對線上問題抱有敬畏之心。2.保留問題現場:方便后續排查和定位問題。3.信息及時同步:同步相關問題信息和跟進進度給相關人員,比如leader、業務、關聯方。4.影響評估及止損:和業務一起評估影響,如果產生實際損失,優先恢復服務,及時止損。恢復服務常用方法:回滾,重啟,擴容,禁用節點,功能降級等。盡快止損是應對線上問題的第一優先級,如果其他環節和這個有沖突,比如保留現場會延長影響時間繼續產生損失,先犧牲掉現場,優先止損,事后再想辦法復現問題進行定位。5.二次確認:服務恢復后,要繼續關注技術指標和業務指標一段時間,確認是否正常。
如何定位問題原因呢,需要從這幾個方向出發:1.充足的知識儲備:對于相關問題,如果沒有相關知識打底,是很難找出問題的,比如分析并發問題但是對并發編程并不熟悉,就很難找到問題根源,只能靠猜。2.善于使用各種輔助工具:比如日志平臺、鏈路追蹤、各種監控工具、JVM性能診斷工具等。3.合適的方法:針對不同的問題,可能分析思路和方法不一樣,需要根據實際場景動態決策。比如有的直接看日志就可以判斷問題根源,有的需要測試環境復現,有的需要將問題逐步縮小范圍再排查等。
5.7 加強日常巡檢和階段性復盤
除了上面介紹的預防和應急方法,還有一點很重要,就是日常定期檢查,長期關注系統穩定性,比如系統的慢SQL,偶爾的接口超時,死信消息等,一定要慎重對待,持續跟進,定期治理,防范于未然永遠好于臨時救火。
對于典型問題和嚴重事故,要重點復盤,總結經驗教訓,避免同類型問題再犯。無事故情況下,也需要定期進行階段性復盤總結,通過回顧目標,評價結果,分析原因,總結經驗這幾步,沉淀經驗,變成知識庫,方便后續組內分享學習。
簡單總結一下,系統穩定性建設是一件任重而道遠的事,要取得好結果,需要基于資源的合理投入為前提,通過提升團隊穩定性意識,健全相關機制和流程,雙管齊下。過程中不過于激進,平穩安全的進行螺旋式建設,重視總結和優化,逐步完善穩定性建設的各個方面。長期堅持,某一天就會發現,已經取得了明顯的治理效果。
6.后記
穩定性建設是一項龐大且系統的工程,涉及生產流程的各個環節,想把系統穩定性建設做好,不是一蹴而就的,需要長期持續的付出努力。建設治理的過程是艱難和漫長的,流程機制會不停的升級進化,咱們在過程中也就慢慢成長了。對于任何一個還在持續運行和迭代的系統而言,系統穩定性建設就像是一場長期革命,革命尚未成功,同志仍需努力,任重而道遠!
作者介紹
楊迎,轉轉寄賣后端研發工程師,目前負責綜合履約方向業務開發。