成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

肝完這篇穩定性建設萬字總結,誰還吐槽我線上不穩定!

開發 新聞
本文中,作者試圖做個相對“系統”的論述,重點討論“服務穩定性”是什么,應該如何建設。

俗話說“缺啥補啥”。想起寫這么一篇文章,不是因為自己和團隊穩定性建設做得有多好,相反,最近經常被吐槽線上不“穩定”......

回想當年,作者在某度第一個項目中,從0到1擼了一個多月的碼(檢索模塊c/c++)。后面QA測試N輪,硬是沒能提出幾(yi)個有效bug,線上似乎也沒啥動靜。現在卻被人指責穩定性做得不好,這事兒看起來不能忍。

“穩定”這個詞,從用戶到ZF機關,一線研發到大老板,大家似乎都會經常提及。不過作者發現,他們所謂的穩定性,也不見得就是一回事。網上搜了搜,沒看到有什么公認的定義,系統論述這個話題的文檔也不多,講實戰的倒是不少。本文中,作者試圖做個相對“系統”的論述,重點討論“服務穩定性”是什么,應該如何建設。作者之前經歷絕大部分時間都在做后端開發,能力和視野所限,難免會偏服務端。

相比于“系統性”,很多優秀的程序員都只喜歡聽所謂的“干貨”。在“系統性”和“干貨”之間不斷地糾結中,作者艱難地完成了本文。

全文基本沒什么新鮮玩意,很多都是老生常談,也借鑒了非常多的來源。作者只是努力整理并重新組織在了一起。因為來源太龐雜,我就沒法一一例舉相關出處,如有侵權,請聯系作者刪除。這里一并謝過執導過我,幫助過我和分享自己的知識到互聯網的所有大佬們!

我們都在聊什么

“穩定性”其實還挺難定義的。讓我們先看幾個英文單詞:Availability, Reliability, Stability。

  • Availability

經常被翻譯成可用性。看到這個單詞,相信大部分人腦子里應該都會呈現很多個9。看圖1,4個9的穩定性意味著一年宕機時間不能超過53min,其實是非常難的。可用性這個概念關注的是系統故障時長。實際上,我們平常會更關注這個宕機時間如何定義的。很多人說自己服務可用性是99.99%,不要輕易相信。你去幫他review下,會驚喜地發現,他可以通過宕機時間本身的定義任意調整這個值。所以如果是上下游關系,還是先把這個指標定義清楚再聊別的會比較好。常見的定義舉例:影響核心功能(e.g.下單)成功率20%以上所持續時間等等。這里的X%還挺重要的。后面的討論中,我們可以依據這個百分比,設計我們的灰度方案等。以免發布個小流量,還搞出P0,不合適。

圖片

圖1 N個9的穩定性

  • Reliability

經常被翻譯成可靠性。相對于可用性,可靠性關注的可能會更泛一些。在服務化的場景下,大家會經常提到SLA。SLA是對一個服務可靠程度的相對量化的約定。其中就可以包括服務可用時長、接口響應時間(如99分位)、錯誤率、集群吞吐率等等。SLA建議盡量用書面形式提供,并且服務提供方和調用方一同簽字畫押。一般還有配套的獎懲措施才能工作的更好。簽字畫押,是為了后面少扯皮。很多時候,處理線上事故總是沒有事故定責時候來的令人緊張刺激。

如果下游沒有提供明確的SLA,我們就得自己根據歷史數據猜測下游各項指標,以便寫出還算合理的代碼,比如超時時間、重試次數、限流大小等等都跟下游服務能力密切相關。當然下游也是動態的,如果對方都無法提供明確的SLA,那其實大家都挺難的。咱們自己提供的服務,最好都有明確的量化指標,隨時提供給上游。如果給不出來,說明我們對自己服務還不夠了解,沒有足夠的掌控能力。

如果是內部系統,老板還會經常關注線上問題數量和等級分布等。處理P0事故緊不緊張?這些都是在努力量化一個系統的可靠程度。

  • Stability

一般翻譯成穩定性。通常是指一個系統如果輸入保持不變,輸出也不會隨著時間發生變化。但是這個穩定性,大概不是我們經常在討論的穩定性。你會發現歪果大佬們一般討論“穩定性”的時候喜歡用Reliability,而國內大佬們卻喜歡用“穩定性”。yy一下,這很可能又是個中國特色的表述了。大概來自于前輩們對我dang“維穩工作”的深刻印象。你會發現我們所謂的“穩定性建設”跟傳統意義上的“維穩工作”基本思路是驚人一致的。監控,隔離,應急處置,特殊事件保障,演練,宣傳培訓等等,請各位客官自行發揮想象力...只是互聯網環境下,我們不太可能期待“輸入不變”。而是,在輸入經常不確定,且系統在不停地迭代的情況下,確保新老輸入都能在預期的時間內得到令用戶滿意的結果。

作者認為,其實概念可能也沒那么重要。“穩定性”這個詞兒似乎也很貼切,有點中國特色挺好。穩定性建設的關鍵是,我們得找到一套大家都認可的指標來衡量他。對于相對獨立的服務,作者推薦用SLA去約定一個服務的穩定性,并盡最大努力達成這個承諾。對于服務提供方,SLA不僅是一個承諾,更是對自身量化的要求。當我們都不敢做出承諾的時候,又何談穩定性建設,何談責任與成長?至于怎么定義一個“服務”,一是看業務邊界,二是看組織架構。很多時候組織架構決定系統架構,而SLA制定過程也跟組織架構密不可分。對于終端團隊,我們可以在SLA基礎上做一些擴展,比如增加一些體驗相關指標。有時候個別后端服務掛了,可以做到對用戶無感,反而APP經常crash那可能是個災難。所以,穩定性也得分層去看。

1)Dickerson的可靠性層次模型

其實作者之前也沒聽過該大佬。為了準備這邊文章無意中搜到的。他據說是前谷哥SRE團隊成員。然后后人在谷哥SRE電子書中引述了相關模型。大佬也是借鑒了馬斯洛需求層次模型。馬老師的這個模型中表示,想得到上一層的滿足,你得先保證其下一層已經得到了很好的滿足,否則容易“出事兒”。比如,當我們都沒飯吃了,哪兒還會去關心哪個行業更卷呢?當然當我們很好地實現了某一層,那下一層需求就會是我們最大的動力來源。

圖片

圖2 馬斯洛需求層次

參考M老師的模型,D大佬提出了他的穩定性層次模型,以便幫助SRE團隊更好的保障系統穩定性。

圖片

圖3 Dickerson可靠新層次模型

在D的模型中,他從SRE的視角出發,將穩定性建設也分了7層。

  • 他認為穩定性建設最基礎是監控(Monitoring)。沒有監控,一個服務是否穩定無從談起。我們首先得知道服務運行情況,當系統哪里出了故障,我們需要及時發現(告警)。
  • 當獲知系統出故障后,SRE們需要作出一些應急響應(Incident Response),包括24小時on-call機制,系統降級預案,協同相關方進行進一步分析,定位最終原因并修復上線。
  • 事后,還需要組織進行深度復盤和根因分析(Postmortem/Root Cause Analysis)。我們需要做到從失敗中學習,并盡量保證未來不會掉進同樣的坑。
  • 前三步都是在做一些防御工事,我們應該盡量在測試階段就發現問題,并通過科學的發布過程來保證不會輕易引入新的線上問題(Testing+Release procedures)。
  • SRE們還需要關注容量需求的變化情況(Capacity Planning)。系統是動態的,我們需要盡力做到讓資源在適當的時機,能夠靈活的調配到真正需要他的地方。
  • 以上做好之后,還需要關注一些研發的工作(Development)。這部分包括原先的系統實現是否合理,從問題反推,是否可以有更合理的設計,并推動優化。當然還有一些必要的工具也需要開發。
  • 穩定性最終極要關注的是產品本身(Product)。從用戶角度,穩定性意味著什么?哪些是他們核心關注的?我們應該努力通過產品和流程設計等減少用戶對系統故障的感知,甚至做到無感。

2)本文討論框架

可能大部分國內互聯網公司沒有真正的SRE團隊。即使有這樣的團隊,據我所知他們可能更關注一些更宏觀的穩定性建設。日常的服務級別的線上穩定性保障,一般都是由研發團隊主要負責的(一般是事故主要責任方)。因此本文中從一個一線研發團隊視角出發,去討論穩定性建設該如何做。

事實上不管是R&D還是SRE團隊,要關注的問題是相同的,只是視角略有不同。既然上面鋪墊了這么多,作者也參考D大佬的層次模型,引出下面的穩定性框架圖(向大佬們致敬)。當然所謂框架,也沒什么新意,更多是方便我后續組織文章。

圖片

圖4 本文討論的穩定性建設框架

在上圖的框架下,雖然也有分層,但跟D不同,作者認為沒有誰比誰重要或者上層強依賴下層關系。只是為了討論方便可以分層去看。傳說中的“既要也要還要”,總是那么的“正確”。我們很難在這些層次上進行取舍,只能說都很重要。作為一個R&D工程師,我們需要時刻關注所有這些方面的問題,最多可以根據自己團隊當前狀況和急迫程度判斷優先級。下面會逐個去討論。

穩定性建設該如何做

因為篇幅和視野限制,本文無法求全,也不太可能非常深入。如果能拋磚引玉,作者就很開心了。

1、梳理

梳理其實可以沒有,理想情況是我們對自己的系統一直都非常熟悉,知道他是怎么工作的,目前他還存在什么問題。但現實可能是:

  • 我們一直在非常“著急地”上著線,周而復始。因為“著急”,我們當時做了很多折中,做了很多臨時的事情。說好的后面優化,一直都還在后面。甚至因為人員輪換,可能都已經不記得當時埋了哪些雷;
  • 可能你剛接手了一個新的系統(和團隊)。當然,你也可以理解梳理為一種復盤。只是他可能沒辦法那么頻繁。

那我們需要梳理什么呢?這個其實沒有標準答案,得看系統和團隊當前情況而定。下圖針對一般情況羅列了一些常見的梳理項。可以根據實際情況進行增減。這也適用于我們快速去熟悉一個新接手的系統。

圖片

圖5 梳理

梳理的過程很多時候都不是一個人可以完成的。我們需要協調很多人參與進來,并進行集中串講,共同分析等。不要一梳理就梳理幾個月。類似迭代開發,我們也可以逐步去梳理,甚至還需要跌帶著去做。當一個團隊人員流動比較大時,新人串講也是挺好的一個時機。

當一個相對理想的梳理工作完成之后,我們大概能知道當前系統現狀是什么,有哪些穩定性隱患。很多時候知道隱患在哪里,比排除和優化更重要。剩下的就是按優先級排期逐一解決了。梳理本身也會幫助我們重新審視自己的系統,加深對他的理解。這對于后續迭代開發,線上問題跟進等都有莫大的好處。所以,當覺得自己團隊沒事兒干的時候(往往都是錯覺),可以讓大家多去梳理(串講)一遍自己的系統。

這一步,還有個重要產出是:哪些業務指標是需要重點關注的,核心接口有哪些。這部分在下一節中會重點討論。

2、監控&Trace

1)監控

監控大家應該都不陌生。在上文中我們也梳理出來了當前服務核心指標和核心接口都有哪些(新項目應該是在設計階段就應該定義好)。我們需要重點圍繞這些指標和接口進行監控建設。監控主要目標是當服務異常時,我們能第一時間感知,以便盡早介入,盡快止損。另外,通過合理的監控設計,我們還可能盡量的縮小問題范圍,幫助我們定位問題根因。缺失有效監控,我們就是個瞎子,每天都掉坑也是正常的。

監控大致可以分成三層去看,本文只討論業務層。

圖片

  • 核心業務指標監控

這個經常不被重視,但他卻是最重要的。我們應該首先站在業務視角去看到底應該關注哪些指標,然后再去想辦法監控這些指標。既然說是業務指標,肯定就跟業務本身有關了,所以各個系統可能都不一樣。舉例,對于一個訂單系統,那么我們關注的核心指標可能有:下單量、成單量、取消量、超時未支付量等等。然后我們想辦法對這些指標進行準實時監控。當這些指標有明顯異常,可以即刻發出告警。

當業務數據較為稀疏時,秒級監控可能經常會誤告警,我們可以適當把時間窗口拉長一點看,比如降級為分鐘級監控。甚至我們可以根據業務高峰期等自動調整監控周期。

這里核心是如何定義好一個指標。當指標定義明確,以咱們的聰明才智相信總能有辦法監控他,并且總能找到一些報警策略(不行上AI),使其足夠靈敏,誤報警概率也還能接受。常見的監控手段包括基于log和數據庫binlog的監控。極端一點的情況,我們可能需要在業務代碼里單獨為這些指標打log(記文本或寫庫)。所以說,監控設計也是系統設計的必要組成部分,最好前期就考慮好。

  • 核心接口監控

接口監控應該不用我多說。重點就那三個指標,QPS、延遲和錯誤率。這里錯誤率的統計,對于錯誤碼規范有要求以外,其他基本都是標配。做細致一點,需要對接口調用方單獨做監控。比如接口QPS突然飆升,我們需要盡快知道到底是哪個來源。

  • 下游依賴監控

下游可能是服務提供方、也可能是個中間件。中間件一般都有單獨團隊維護,他們會提供通用的監控大盤等。業務方要做的更多是從自己的視角看這些被依賴方他的實際運行情況如何。因為絕大部分依賴都是通過RPC進行的,所以類似接口監控,我們需要關注下游調用成功率,響應時間等等。當然如果下游都提供了監控大盤,可以考慮把兩者合并一下,找起來方便。

  • 監控大盤

呈現很多時候都挺重要的,就像如果有人PPT寫得好,你不能否認他其他方面也大概率比咱更優秀。為了看起來方便,我們需要分層去建設監控大盤。每個大盤也不能太大了。大盤在線上走查,上線回歸等場景必不可少。這里沒什么新鮮的,把分層設計好就差不多了,不啰嗦了。

2)告警

告警策略其實可以復雜到很多大佬都在談AI了。常見的就是同比異常、環比異常、超閾值等。策略核心就是在召回和準確性之間各種折中。作者的觀點是寧可誤報,不能漏報。誤報得多了,我們自然就有動力去優化了。至于告警方式,傳統的,電話、短信為主,釘釘、email為輔。報警內容一定要盡量多的帶一些具體指標項和數據等(注意信息安全,運營商你們懂得),以便我們快速判斷問題嚴重性。

很多時候,我們報警策略本身可能也會不穩定,也可能設計得不夠靈敏。這時候就要求我們去主動去巡視。比如上完線,都去看看大盤是否有異常,值班同學每天定時掃幾眼(尤其高峰時)。當然機器和服務太多了,無法人肉去看大盤時,也可以搞一些自動巡視腳本提效。

3)Trace

他可以有個高大上的名字“根因分析系統”。通過監控,我們知道系統有問題了,這個還不夠。當我們及時止損之后,應該抓緊定位根因。trace系統一般依賴系統日志采集,并通過二次索引,提供快速的查詢線上問題和統計分析的能力。通過trace,我們除了追蹤單個請求鏈,還可以生成系統整體拓撲,系統熱點分析,整個鏈路性能分析等等。這里log設計和規范是最關鍵的。如果系統里的logid(traceid)都還沒打通,團隊都不知道spanid是個啥的話,那工具其實也可能還不重要。當然最好是這些都在框架層面就解決了,沒必要讓每個程序員都關注他們的存在(除定位問題時候以外)。最終,trace還是需要有個強大的配套工具支持的。這個數據量可能會很大(降級為采樣?),分析效率又很關鍵,沒有好用的工具,全靠寫腳本很多時候都不現實。

3、應急處置 & Case Study

1)應急處置

說白了就是線上問題處理。因為每個系統設計和現狀,甚至每次遇到的問題都不一樣,所以很難搞出一套通用的機制或方法論。這里只是簡單聊一聊一些思路。

① 責任人

當線上有問題,我們首先得有明確的責任人去跟進。如果是監控告警發現的問題,那么誰收到告警,誰就應該是那個責任人(不怕多,就怕沒人跟)。“首問責任制”聽過的朋友大概也能知道我在哪兒被蹂躪過了....其他情況,通過值班機制等保證每個關鍵時間段(比如高峰期),都有明確的人能及時跟進。每個團隊情況不同,可以自行設計。這個值班人可能是研發,可能是SRE,也可能是個技術支持之類的。

② 判斷影響面

作為責任人,首先要做到遇事不慌,快速判斷影響面。看核心業務大盤是否受影響。影響了核心業務,那就立刻需要升級處理。緊急問題應立即通報。如果業務大盤影響不大,那其他報警叫得再歡,咱們其實也不虛(再論監控的重要性)。一般問題,可以考慮進一步確認影響,或者直接跳到“找根因”環節。

③ 通報

需要明確緊急問題通報范圍,讓更多的人參與進來協助處理緊急狀況。其中至少要包含自己leader。

④ 止損

通報后,緊急事件應優先考慮止損。

  • 近期有相關上線,優先考慮回滾(比如時間點比較接近,或改動跟該功能有關)。
  • 如果是流量突增,那應該考慮限流+緊急擴容。
  • 如果是下游服務異常,那么應該考慮降級。
  • 如果單個集群問題,考慮切集群(機房)。這里,你會發現各種case,其實是無法枚舉完的。

唯一共同點是,每次事故原因,起初看起來都很迷,最后定位后都很傻X,而且總是驚人的相似。所以應急預案,需要平時積累,現場去想,大概率就遲了。預案主要是依據歷史事故和架構師們的經驗,不斷積累的過程。每個業務不同的故障預案都不同。上面止損里簡單描述了集中常見故障及處理預案。作者想強調的是,預案不應該只是文本,而應該是經過驗證的(演練過)極簡操作步驟,最好是已經工具化(e.g. XX腳本)的。

⑤ 找根因

當我們有效止損之后,應該把精力放在尋找跟因上。如果發現無法快速止損,也別太執著了,至少可以分一部分人力找根因了。定位問題,有時候看起來是一門玄學,大神一出馬,往往很快就能破案。而且你會發現,大神總是那幾個人。他們為什么比咱快呢?我想,首先肯定不是因為他代碼寫得好,也不見得有咱寫得多(某些人眼里的“技術牛”)。而是,他對系統更熟悉,他了解系統整體架構,知道哪里是一些脆弱環節,容易出問題,上下游依賴情況怎么樣,哪個下游比咱還不靠譜;他經常去聽各種復盤,知道類似的問題之前出現過,是什么原因導致的;他對各種工具更熟悉,比如trace,監控系統等,所以效率更高。慢慢的他們就形成了一套自己的方法論,甚至可以從現象猜測出幾個最可能的原因,然后去逐一驗證。可見,平時積累非常重要,要對自己所用的框架,所負責的模塊上下游都要做到盡可能多的了解,甚至去多讀一讀他們的源碼。

線上如果有穩定復現的環境,可以下線一臺服務器專門定位問題。如果線上無法快速定位,可以考慮線下復現。所以線下鏡像環境也是很重要的。一方面,可以用于平時線下測試,當線上有問題時候,也可以用來復現問題。能復現的問題,其實就沒什么難度了。最后,大家一定要相信,沒有什么問題是無法定位的,事實也是如此。

很多時候無法定位,都是缺少關鍵日志,所以要養成各種異常分支都需要打個日志的好習慣,我們開始時候不要怕日志多,告警多,等我們無法容忍的時候總會有人去優化他。但是一旦少日志,沒告警的時候就欲哭無淚了。

根因找到之后,我們需要上線驗證,并統計和修復損失了。

2)Case Study

其實是一種特殊的復盤。每次的線上問題,都是我們成本最高的一次學習機會。所以,一定要珍惜,要認真對待。相信大家也經常做,所以具體復盤模板這些就不用我多說了,相信每個公司都有自己的一套。幾個tips:

1)不要把Case Study搞成批斗大會。雖然定責很重要,但是不用太糾結這個。我們得有一套相對客觀的定責標準,省得有人糾結這個。比如之前我們就約定線上事故由源頭負主要責任(很多時候是全部),什么上游保護下游,上游限流沒生效,上游沒合理重試這些都是額(che)外(dan)的。還是得想方設法保證自己不掛,掛了就得認。我們更多要去想怎么從失敗中學習,不斷完善自己的系統。我能想得到唯一需要我們保護的下游可能是MySQL,因為他實在太老,太脆弱了,可得對她溫柔一點。

2)圍繞根因要多去想是否還有其他類似隱患,要真正做到舉一反三,比如排查其他模塊是否有類似問題,比如拉上上下游關聯系統一起看怎么全鏈路優化,比如故障期間產品提示等是否可以更友好一點等等。

3)對于發現的問題要做好保護:

  • 監控配置和日志打印是否需要優化?以便下次有類似問題不用這么辛苦去定位。
  • 相關代碼是否需要重構?
  • 測試用例增加了嗎?
  • 線上問題預案是否需要增加相關條目?

4、測試&發布

1)測試

質量跟穩定性很多時候都是劃等號的。質量保障是整個軟件工程核心活動,是研發人員的職業底線。對于工程團隊,如果這個底線沒守住,那其他努力都將變得黯淡無光。我們必然要竭盡全力,讓問題在上線發布前就發現并解決了。

測試如此重要,以至于國內很多互聯網公司都有專職的QA團隊。當然,即使有了QA團隊,測試工作也并非全部由該團隊完全負責。研發人員要對自己編寫的代碼負全部責任,有沒有QA團隊都一樣。設有QA團隊,有提測這些額外的流程,更多是為了再多一層保障。

作者沒有實際研究過QA團隊自己是如何定位并規劃他們團隊的工作的,所以以下都是站在研發角度講的,理解有偏差的請見諒。因為測試相關話題太大了,這里只是簡單羅列一些常見的測試類型。至于怎么做,如何算做得好這個估計得再好好學習學習才行。

① 單元測試(Unit Testing)

指單個函數、模塊或功能級的測試,屬于白盒測試。一般都是由研發人員自己完成。敏捷團隊應該都了解測試驅動開發(TDD)。在一些傳統軟件行業,如通信領域等可靠性要求較高的單位可能工作的會相對好一些。互聯網領域,尤其其中做上層業務開發的,真正把TDD用得好的并不多。不過一些思想值得我們時刻參考。要想把單測寫好,維護好其實并不那么容易。首先,寫出來的代碼,得對測試友好。這對于編碼能力是有一定要求的。往往抱怨單測很浪費時間的,大概率是代碼抽象,尤其接口層面設計,分層這些沒有做好的那些人。另外,測試用例需要維護,是有成本的。甚至測試用例的代碼量會遠遠大于業務代碼。不過要知道自動化測試用例,不是為了一次功能測試而編寫的,更多是一個文檔和一種保護。保護測試好的代碼不會被后人輕易破壞。他可以反復、全自動執行,所以疊加起來的價值可以很大。有了自動化測試用例,我們就可以在每次代碼變更時候,都可以自動跑一下這些case。這個屬于check in build的一部分。因為case數量會越積累越多,我們為了不影響開發效率,可以把這些case分成快速的和全量的。快的是每次check in都會執行(check in build),慢的可以是天級執行(daily build)。

② 集成測試(Integration Testing)

指將已經完成了單元測試的模塊等組合起來測試,比如接口測試,某個流程測試等等。他一般針對某個功能點(特性)進行測試,通常屬于黑盒測試。研發內部的聯調測試,QA的大部分測試工作,都屬于這個范疇。

③ 系統測試(System Testing)

指從交付角度(用戶視角)進行的更宏觀的測試。操作系統適配測試,低端機適配測試,弱網測試,安全測試,性能測試,壓力測試等等,都可以歸為系統測試大類。

④ 回歸測試(Regression Testing)

當系統有變更時,我們通過回歸測試保證原有功能都沒有被破壞。一般分為線上和線下,而且希望這部分自動化程度越高越好。靠人工去做回歸測試將必然是個悲慘的故事。

⑤ 冒煙測試(Smoke Testing)

據說是最早做板子的前輩們,在設計好一塊板子之后先通電看看會不會哪里冒煙。如果冒煙就說明根本沒必要進行任何其他測試了,直接回爐重造。在軟件行業,一般指的QA團隊的準入測試吧。一般要求他能自動運行,且速度要快一些。冒煙沒通過,直接打回提測流程。

⑥ α測試(Alpha Testing)

一般是指客戶側在正式交付前的驗證測試。不過互聯網行業很少提這個了。

⑦ β測試(Beta Testing)

將產品交付給少部分用戶,然后進行實際場景應用,并收集反饋。我們一般叫小流量測試或灰度測試了,換了個名字。

⑧ 壓力測試(Stress Testing)

測試一些臨界壓力情況下的系統表現。比如系統最大同時在線的用戶數,最大支持的輸入大小,模擬用戶惡意下單等等。一般是針對系統級的全流程測試。當然如果某個接口很重要,有時候也會說做接口壓測,實際上就跟下面的性能測試有點混淆了,不過這個不重要。在to C場景,壓測是非常重要的,如果有一套成熟的壓測體系,那恭喜你,至少心里會踏實很多。當然搞一套有效的壓測體系,我們也需要不小的投入。可能會面臨的幾個挑戰:

  • 壓測工具本身并發度是否可以達到我們的要求?
  • 壓測請求如何模擬,線上錄制?簽名、token這些都很麻煩。
  • 壓測流量如何標記?
  • 提交接口怎么壓?產生的很多“垃圾數據”如何清理,如何跟真實數據隔離會是個大麻煩(影子表?)
  • 全鏈路壓測,涉及到多個團隊,甚至是多個部門協同。如果要做架構升級(比如增加流量標記),那可能至少都是按月計的。壓測期間很可能還會影響線上服務,深夜也有用戶咋辦?

⑨ 性能測試(Performance Testing)

比如某個接口的單機性能,集群性能等。

⑩ 故障演練(Recovery testing)

模擬各種故障,比如下游宕機,數據庫離線等等,然后看系統表現是否跟設計一致。可以認為是系統級的異常測試。Recovery testing還會關注當故障恢復后,系統是否可以自動復原。

還有很多名詞,有的作者也沒接觸過,就不再發散了。

2)發布

據不完全、不可靠統計,70%以上的線上事故是由代碼變更(包括配置)引起的。可見把測試好的代碼發布上線是一個非常高風險的事情。為了盡量降低這個風險,人們搞出了各種各樣的灰度策略和機制。他的本質是:1)開發和測試人員沒能測到的問題,就讓更多的用戶幫我們測試(眾測);2)為了控制影響面,需要逐步放量,爭取在最小的影響面下發現問題。下面簡單介紹下常見的幾種灰度方案。

① 金絲雀發布

礦工的故事大家應該都聽過了,不再贅述。其實很多時候我們所謂的灰度發布,基本就是等價于金絲雀發布了。通常我們會把集群分成幾個集群,典型的預發布、小流量和全量集群(當然可以有更多級)。然后,逐步放量。其中預發布一般不對外,我們把代碼上到預發布環境,通過自動化回歸腳本+人肉,進行新老功能的回歸。如果有內測環節那就更好了,找一些公司內部的用戶幫忙驗證一下。到小流量環境是要有真實的公網流量的。我們一定要預留足夠的時間來收集反饋。當然具體時間是根據版本大小和廠子現狀定的。收集反饋最核心就是之前建好的監控大盤了。如果能收集真實的用戶反饋那就更好了。VoC自動檢測,其實也算監控一種吧。比如直播系統,用戶刷屏“卡”“卡死”...

金絲雀發布估計是用的最多的一種發布方式。其核心是制定一套分流機制。最簡單就是在router層按流量隨機分流了。如果你的服務只跟流量本身有關(典型的就是不用登錄的場景,如百度搜索),那用服務器灰度就夠了。1臺,10%,100%...如果想根據用戶分流(要求一個用戶要不用舊版服務,要不就用新版的),那么就得需要一些設計,典型的是在HTTP頭里增加一些分流標識等。如果再復雜的分流策略,那么就得自己搞個gateway了。有集中存儲的時候,比如MySQL,那么存儲層面要不要也分開,也是個問題。

客戶端在各大應用市場的發布策略,一般也都屬于這一類。

② 藍綠發布

很少用。大致思想是搞兩套集群,藍色是老的,新的是綠的。起初流量指向藍的,等把代碼部署到綠的,驗證ok之后把流量指向綠的。下一輪發布,把顏色交換一下。好處是回滾快,成本就是多了100%的冗余。可以做細一點,比如類似滾動發布,每一輪(比如10%)都走藍綠,到下一輪時就回收藍色當綠色。這樣就只需要10%的冗余了。

③ 影子發布

核心是流量復制。老版本依然保持服務,新版本部署到新環境后,把老版本的流量copy到新版本(可以是部分流量),然后驗證新版本的功能。我們做了一輪純粹的技術重構后,對比新老版本結果是否一致,經常這么玩。如果機器資源不太夠,也可以通過代碼開關進行相關驗證。

④ A/B測試

很多策略模塊喜歡A/B。其部署可能都在一個集群,只是策略插件有多分,我們通過程序開關控制不同的用戶走不同策略,然后對比不同策略的效果。A/B可以很復雜,也可以認為是金絲雀的一種吧。不展開了,還有專門做ToB的A/B系統的單位,可見其復雜度和價值。

3)CI/CD

聊到DevOps,都會說到這兩個概念。這兩個單詞分別是Continuous Integration和Continuous Delivery的縮寫。其核心是通過一對自動化的工具和流程,使得我們迭代開發和發布變得更高效,更有保障。話題有點大,不討論了,附一張圖:

圖片

圖6 典型的CI/CD流程

5、設計開發

軟件設計和開發,應該是我們最熟悉的了。不過這次咱們從穩定性視角再去看一看。很多事情在設計開發階段考慮好,才是ROI最高的。

1)設計

軟件設計也是個很大的概念。什么是一個好的設計?估計不會有什么明確的答案。但是一個糟糕的設計,會導致我們迭代成本越來越高,穩定性保障變得異常困難 。前輩大佬們基于自己的實踐經驗,概括了一些大家耳熟能詳的設計原則。我們遵循這些原則,不見得能解決所有問題,但是可以規避很多可能的大坑。

① KISS(Keep It Simple, Stupid)原則

愛因斯坦講過:如果你不能簡單的解釋它,說明你還沒有足夠的理解它。某度的“簡單可依賴”似乎也是在強調這個事情。只有它足夠“簡單”,它才更“可依賴”的。簡單在軟件工程里意味著:

  • 當有故障時,我們可以快速的定位;
  • 當重構或接手時,我們可以更容易;
  • 我們往往都少寫了很多行代碼,無論是開發效率還是維護成本都會更低;
  • 能做出簡單的設計,意味著我們對這個事情看得更透,實現質量更高。

為了簡單我們:

  • 要盡量避免引入一些大家不熟知或未被驗證的技術棧;
  • 不需要一些隱晦的實現,可能他看起來很cool;
  • 不提倡每個工程師都最大化自己的“個性”,需要遵循一些規范,雖然他看起來很笨重;
  • 最重要的是我們一定要始終相信總會有更簡單直接的實現。

② YAGNI(You Ain’t Gonna Need It)原則

意思是,如果一個事情你不是今天就需要,那大概率就是你不需要的。我們總希望自己能高瞻遠矚,一勞永逸,偶爾還想秀一秀技術。但事實是,我們不管是產品功能,還是代碼實現,總是有很多無用或者很少用到的東西(2/8定律)。多余的這部分反而是更容易出錯且維護成本更高的(因為團隊對這部分更陌生,且升級迭代時經常忽略這部分)。所以我們要盡量杜絕過度設計,包括畫蛇添足,過于超前等等。很多時候識別真正現在就需要的東西,還是有點難度的。作者認為,

  • 如果無法做到事前判斷,那時候一定要做到時候及時評估。該刪就得大膽刪,因為維護成本往往比開發成本更高。這個評估過程,也會對我們未來的判斷帶來一些經驗和依據;
  • 判斷一個事情暫時用不上,那么就看我們現在實現和未來實現成本差異有多大。如果差別不大,或現在做成本小那么一丟丟,那么就放到后面再去實現吧。做好擴展能力設計等就ok了。

所謂前瞻性設計,更多是在思考和調研階段要盡量考慮周全,想好各種異常和未來擴展性需求。而真正實現的時候,做取舍才能體現架構師真正的實力。很多時候我們倡導提供簡單直接的實現,然后做好兜底。兜底可以很暴力,只要他發生的頻率不高,很多時候都是可以接受的。等我們無法容忍的時候,就有動力優化了。敏捷開發中有很多這方面的思考:我們持續交付那些優先級高的最小集合。讓系統先跑起來,然后根據用戶(可能是甲方)實際使用反饋再決策需要增加哪些特性或哪些體驗需要優化。

③ DRY(Don’t Repeat Yourself)原則

顧名思義,要以Ctrl C/Ctrl V為恥。我們應該盡最大努力杜絕重復代碼。提高代碼復用,對于開發、維護效率至關重要。更重要的是,我們不該把測試等額外的精力浪費在重復測試幾乎相同的代碼上。為了減少重復,我們自然會對自己的代碼做更多的分層、抽象、局部重構等,使得每段代碼,每個函數他的職責會越來越明確,單一。

④ SOLID原則

大名鼎鼎,大家應該都非常熟悉了。針對面向對象場景,大佬們(一說是Robert J. Martin,即Uncle Bob首次提出的,應該不全是他的)總結出了五條原則,目的是讓代碼可維護性更高,更好理解,更容易擴展,避免隨著代碼量的增加代碼越來越復雜。從穩定性角度,遵循SOLID原則,也會使得我們的代碼變更更加可控,影響面不會被無限放大。這幾個原則實在太出名了,請各位客觀自行查閱相關資料吧。附圖如下:

圖片

圖7 SOLID原則

⑤ IDEALS原則

分布式系統,尤其是微服務盛行的今天,有人覺得也應該有類似SOLID的一些準則,用來指導整體微服務架構設計和實現。2020年時候,InfoQ上有位大佬提出了IDEALS的概念,目前看影響肯定沒有SOLID那么大,但可以對我們帶來一些啟發。遵循這些原則,雖然不能解決所有問題,但是可以讓我們的設計和技術選型有據可依,至少不會跑太偏。下面大致解釋下概念:

IDEALS是以下幾個單詞的首字母拼接:Interface segregation, Deployability (is on you), Event-driven, Availability over consistency, Loose coupling, Single responsibility。

  • 接口隔離(Interface segregation)

希望通過面向不同的客戶、不同的應用場景提供單獨的接口,減少不同客戶之間的改動影響到其他客戶。這里最典型的一個問題是web和移動APP是否要提供獨立的接口?BFF(Backend for Frontends)就是非常典型的一個設計模式,可以自行了解下。

  • 可部署性(Deployability (is on you))

中文翻譯不一定準確,僅供參考。微服務架構使得線上部署單元變多了,所以如何更高效的發布和監控變得更加重要。這里好的工具對效率的提升至關重要。下面幾類技術和工具,興許都能用得上:容器化(Docker+k8s)、Service Mesh(Istio含Envoy)、API Gateway(提供協議轉換、接口路由、安全控制、熔斷、限流、配額管理、流量監控等等能力,部分能力逐漸在被Service Mesh和開發框架,如Spring Cloud等代替。Kong/tyk),Serverless(各云廠商提供的云函數FaaS),監控工具(Prometheus/Grafana,還可以關注laiwei老師的Open Falcon和最新的Nightingale),日志采集(其實很多監控方案都自帶了采集能力,ELK/splunk),鏈路追蹤(Zipkin/Jaeger),DevOps(文化+工具+實踐),灰度發布,IaC(Infrastructure as Code),CI/CD(Jenkins/Argo CD/Flux)。如果你有個非常靠譜的基礎架構或運維團隊,那么以上其實更多是關注如何使用就好了。如果沒有或你就是那個團隊成員,恭喜你,在微服務和云原生的沖擊下,這塊更新換代還是比較快的,要學習掌握的真不少。關鍵這些都是一些基礎設施,對穩定性和易用性要求都極高。

  • 事件驅動(Event-Driven)

雖然他不等價于異步模式,但他們密不可分。微服務架構中,鼓勵大家大量使用基于消息的異步通信。這是調用方和服務提供方之間比較徹底的解耦方式。一方面,可以做到消峰,高并發情況下,也不會因為下游服務處理能力導致拒絕服務;另一方面,消費方可以根據消息量靈活擴縮容,而且還給你留了一定的反應時間。目前MQ中間件基本都已經很成熟了,一般場景下甚至丟消息都不用太考慮,只有增加一些兜底措施就好。另外,MQ的可用性一般都遠高于業務服務,所以也不用擔心引入他帶來的穩定性損失。只要對于響應時間沒有特別敏感,原則上能異步就異步。挑戰可能是對于業務本身的事件驅動的抽象,前端的體驗設計和MQ本身的規劃和管理上吧。

  • 可用性勝過一致性(Availability over Consistency)

在大部分互聯網場景下,我們更注重可用性,而對于一致性,降級為了追求最終一致性。CAP原理相信大家都非常熟悉了,而且這個話題有點大。這里就當做是一種常識吧。Command Query Responsibility Segregation (CQRS) 可以了解下,附一張原圖:

圖片

圖8 CQRS

  • 松耦合(Loose-Coupling)

解耦帶來的好處應該不用解釋了。具體解耦方式也有多種。這里核心不是怎么解,而是怎么發現。比如一個模塊本來很簡單,后來由兩個團隊共同維護,那可能這兩個團隊分工合作就有耦合了,可以考慮拆分。如果一個系統足夠簡單,數據量也不大,非得搞個CQRS,全異步那也只是在徒增煩惱,不見得能真的體會到“解耦”的好處。

  • 單一職責(Single Responsibility)

類似SOLID里的S,他強調的是服務內部要高內聚。很容易理解,但是可能很難把握。服務分的太粗,就逐漸退化成單體應用了。如果拆的特別細碎,部署運維會是個問題,另外還會額外增加一些RPC代價。個人一些簡單原則(只要糾結,肯定都能找到一個反例,僅供參考):

  1. 一個微服務,盡量對應一個數據庫。這里,如果某種場景必須要有事務保證,那相關操作必然得在一個服務。不過建議盡量減少大事務,而是追求最終一致性,上面有討論;
  2. 如果業務場景中,絕大部分請求,都會涉及多個同一層“模塊”(分層是另一個維度,不算),那這些“模塊”就放到一個服務吧,除非有很強的拆開的理由。這里如果用DDD描述可能更容易理解。不過作者對DDD理解不夠深入,不敢提;
  3. 組織架構決定系統架構,不同團隊維護的,就想辦法從代碼層面拆清楚;
  4. 如果拆開目前沒有引入無法接受的成本,那么就先拆開吧。合并,一般都會比拆分成本更小。
  5. 拆分過程可能比結果更重要。能把一個看起來凌亂的事情抽象成多個相對獨立的事務的組合,必然會降低其復雜度。如果考慮運維成本等,可以先只是邏輯拆分,物理上可以是一個包,一個節點。

2)開發

開發過程其實真正寫碼的時間也很少,這里強調的更多是一些局部設計和編碼過程中要避免的一些坑。當然我們編寫出來的代碼質量才是最終決定系統運行情況的根本保障。各大廠應該都會有一些開發手冊等。其中最出名的應該是《阿里巴巴java開發手冊》了,作者認為沒有之一。手冊中自稱愿景是“碼出高效,碼出質量”。很顯然通過此類手冊,我們希望一方面能規范一些開發過程,另外,也通過一些基礎的保障和警示,提高程序員編碼質量。其中每一條規約后面,可能都深藏著無數深坑和歷史上在此坑掉下去的大俠們。

我們也可以從穩定性角度制定類似規范。我們要做的是不斷完善自己的開發規范同時,應該根據團隊實際遇到的一些問題,復盤的線上事故等來不斷沉淀自己團隊的一些相應的規范和禁忌。線上事故是我們繳的最貴的學費,不要輕易浪費他。

有規范是一方面,更重要的是執行。這塊可能更多是依賴一線leader的執行力和管理能力了。

6、工具&文化

這倆放一起,其實沒那么生硬。有一種文化叫“工具文化”~

1)工具

其實前面聊了很多工具相關的事情了。這些工具包括一些開源項目或商業軟件,也可能是團隊自研小工具等等。我們經常講能依靠工具就不要依賴流程,能建立流程就不要依賴人的主動性。合理使用工具,讓一切能自動化的自動化,一方面是提高執行效率,另一方面降低人為引入的失誤風險。一些常規,繁瑣或容易出錯的事情,我們就應該考慮建設相對應的工具。比如一些環境搭建,代碼檢查,自動化測試和CI/CD流程等都可以完全交給工具去完成。除此之外,線上trace,debug,兜底操作等都依賴工具支持。還可以例舉很多場景。

作為一名優秀的工程師,咱們能自己動手提升自身工作效率,降低犯錯的概率,為什么不多去努力呢?

相反,如果工具層面欠缺太多,那就該咬咬牙把這塊能力先補上吧。比如,日志采集和監控,CI/CD,如果沒有很好的工具支撐,那我們就需要(反復地)做很多額外的事情,而且隨著系統演進和團隊壯大,這部分工作量都是成倍的增長的。我們就該盡早重視這部分建設。一些小團隊創業型團隊,這部分反而往往被忽略,不被重視。看起來組織永遠沒人力投入,實際上過段時間去統計,你就會發現總的額外投入往往要比工具本身上的投入要大好多倍。

穩定性建設是個無底洞,如果沒有很好地提效工具,那么ROI就會越來越低。如果你想說服你老板加大在穩定性方面的投入,那不得不去講ROI。工具雖然不是全部提效手段,但肯定是最重要的一個。

2)文化

我們通篇都在講穩定性可以怎么怎么保障,看似很系統。實際情況是,很多時候所謂穩定性建設可能都只是有一陣風,吹過之后似乎什么也沒留下。系統在不斷迭代,人員也會不停流動,如果沒有一個好的文化傳承,我們其實無法保證這塊的持續投入和效果。那怎么建設一個團隊的穩定性文化呢?其實這話題可能是我一萬個最不擅長的事情之一了。不過既然提出來了,就簡單分享下此刻的一些認知吧。參考HR部門關于企業文化建設的思路:

首先,提煉它。文化一般都希望能提煉成一兩句話,讓團隊朗朗上口。這樣才能更好的傳播和傳承。我自己團隊,用一句話強調穩定性的重要性:穩定性是我們的底線。意思是,如果穩定性沒有做好,做再多拔高的事情,其實也都可能會歸零。我們不要求一切都以穩定性為前提(很多時候迭代壓力會極端的大),但是要明確意識到,穩定性不管什么時候都是我們的底線,要時刻提醒自己是不是做的足夠好了。至少要做到在當時那個環境下充分評估穩定性風險,并保證最大程度的投入。如果因為一些交付時間等原因,做了一些妥協,那一定要在接下來最快的時間內把穩定性欠債還上。

其次,運營好。文化是需要運營的。作者認為比較實用的一些運營方式有:

1)建立明確的獎懲措施。比如線上事故得有些具體懲罰措施。可以是物質的,也可能是更柔和的。當然做得好的,要多去鼓勵,多去傳播。

2)識別關鍵人員,并加以引導。讓更多的人幫助自己推廣相關理念和要求。比如每個小組的leader,一些核心開發人員。他們在一線,很多時候他們說的話更有感染力。所以一定要先跟這些人員達成一致,并讓他們一方面身體力行;另一方面,作為穩定性文化的堅定傳播者,幫助組織共同傳承和發揚光大。

3)洗腦式宣貫。我們要不停的講一些穩定性方面的意識和實操層面要關注的事情(比如監控設計和發布設計都是系統設計階段要考慮的)。穩定性宣貫有個特別好的時機,那就是線上出故障時,我們一般都會組織復盤或case study。那這時候所有的穩定性主張都可以重新再review下。看我們哪里做得好,哪些點沒做到位。只要堅持高質量的復盤和case study,就可以在團隊內部不斷強化相關意識。而且問題越多,力度越大。問題不多時候有稍微放一放不見得一定是壞事。當然系統不可能沒有問題的,這個度就得管理者自己拿捏了。小道cr問題,qa發現的bug等等只要想強調,就可以組織case study。這里復盤再稍微羅嗦下的是:一方面,復盤時不一定都是全員可以參加,所以復盤結論的通曬就很重要了(不要藏著掖著);另一方面,復盤容易,閉環往往都不是很理想,所以應該更多的去關注閉環效果。其中就可以review下文化,意識層面的改進項。

再者,把它融入到其他文化建設中,形成更廣泛的傳播。穩定性文化單獨拿出來,其實有可能只是一個點。但是像工程師文化,新人融(xi)入(nao),這些都是我們經常會去講,會去做的。那么作為喜歡追求極致的工程師們,能夠容忍自己開發的系統有缺陷嗎?至少應該以此為恥吧?新入職培訓和熟悉業務階段,是否可以專門設置相關課程?作為一個新人,至少應該看一看組織歷史上都犯過哪些錯誤吧?不斷沉淀一些相關案例,讓成員們定期多去關注這些案例。自然就可以從中吸取一些教訓,尤其哪些重復犯的錯誤,都應該被深深地記住。

寫在后面

穩定性建設至關重要。

服務穩定性對于公司口碑,甚至是對其直接的商業利益都有重大影響。歷史上血淋淋的宕機事件、安全事故比比皆是。不知這背后又有多少猿類內心和肉體上留下了揮之不去的烙印。

穩定性建設,對于系統設計,團隊協同效率,程序員自身修養都提出了更高的要求。所以只要堅持投入,對于系統穩定性提升,團隊整體戰斗力提升和成員個人成長都是大有裨益的。

穩定性建設不好做,需要耐心。

1)穩定性建設很多時候都是在做保底線的事情。這就意味著,不出問題甲方(用戶、老板、合作伙伴)基本沒有人能感受到。他們關注到你的時候,大概率線上已經出了事故。所以,想得到大家的欣賞還是挺難的,如果想長期從事相關工作,得做好吃土的準備。不過一般很少有人專門做穩定性建設,更多是在自己開發交付過程中不斷完善系統,使其更讓人放心。

2)穩定性建設投入總是沒保障。我們總是(尤其是在業務初期)著急的開發著新的特性,迭代效率基本就是個無法妥協的事情。如果不咬牙堅持,付出額外的努力,根本就沒法堅持。

3)穩定性建設涉及軟件開發整個生命周期。想每個環節同時都做到理想狀態幾乎不可能。所以也意味著他是個慢功夫,甚至剛開始時候很容易犯左傾冒進主義錯誤,后期又無法堅持長期斗爭。從上到下得有耐心才可能做得更好。

責任編輯:張燕妮 來源: dbaplus社群
相關推薦

2021-04-19 11:12:46

區塊鏈貨幣加密貨幣

2020-09-08 08:15:26

存儲Ceph性能

2022-09-15 08:33:27

安全生產系統Review

2021-05-17 11:22:28

比特幣數字貨幣金融

2010-09-14 13:17:11

無線網絡不穩定

2025-03-18 00:00:01

2023-04-26 18:36:13

2010-09-15 13:27:33

無線信號不穩定

2023-08-22 14:29:05

大前端

2023-06-30 08:43:36

2011-06-29 14:39:29

網站排名

2011-04-01 15:02:43

路由器鏈路

2023-05-25 21:35:00

穩定性建設前端

2021-02-09 08:31:38

線下環境 stable

2011-12-21 09:46:46

程序員

2009-07-27 10:08:14

2020-07-13 08:10:13

軟件設計系統

2020-07-28 08:07:14

ElasticSear

2011-08-01 11:03:15

2023-06-15 11:48:09

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久国产免费看 | 日韩久久久久久 | 亚洲狠狠丁香婷婷综合久久久 | 国产97碰免费视频 | 日本久久福利 | 欧美a在线看 | 日韩在线电影 | 日本天天色 | 久久久久久国产精品免费免费男同 | 蜜桃臀av一区二区三区 | 水蜜桃亚洲一二三四在线 | 日韩最新网址 | 精品久久99| 插插宗合网 | 日本高清视频在线播放 | 亚洲精品自在在线观看 | 欧美在线a | 爱爱爱av| 亚洲国产一区二区三区 | 久久综合亚洲 | 国产免费自拍 | 日韩一区二区三区在线 | 99精品国产一区二区三区 | 日韩成人在线播放 | 欧美日本在线观看 | 国产高清视频在线观看 | 99精品一级欧美片免费播放 | av国产精品 | 在线观看亚洲专区 | 精品国偷自产在线 | 亚洲精品一区二区在线 | 久久久久免费精品国产 | 久久激情五月丁香伊人 | 欧美日韩精品专区 | 色视频在线免费观看 | 午夜精品一区 | 一区二区在线看 | 亚洲国产精品99久久久久久久久 | 欧美日韩视频网站 | 日日爱视频 | 在线一区二区三区 |