桔妹導讀:本文給出其中穩定性相關的規範,這些規範都是順風車成立五年來,對大量真實線上故障覆盤、總結得到的,希望對大家服務的穩定性提升有所幫助。
服務端作為順風車技術部內最大的工程團隊,隨著人員的擴張和迭代,流程規範在其中扮演著原來越重要的角色。一方面規範化可以提高我們的交付質量、交付效率,另一方面,我們也希望在一次次的實戰中不斷的總結,探索出適用於我們團隊的最佳實踐。
基於此,我們制定並推廣了一套適用於服務端開發的可執行、最小限制的工程規範,包括研發流程、穩定性、效能成本等多個方面。
本文給出其中穩定性相關的規範,這些規範都是順風車成立五年來,對大量真實線上故障覆盤、總結得到的,希望對大家服務的穩定性提升有所幫助。
1. 名詞解釋
下文的描述中,會用到很多的技術名詞,為更容易的理解,在這裡對這些名詞做下簡要說明:
-
服務分級: 根據業務需要,一般的我們需要針對最小系統劃分為一級服務,一旦出問題需要第一優先順序跟進。我們將影響業務核心指標(比如發單量、成單量等)的服務定義為一級服務,其他為二級服務。
-
預覽叢集: 和線上生產環境的部署完全一致的一套環境,只是無線上流量,可以內部訪問,叢集內流量閉環。
-
小流量叢集: 和線上生產環境的部署完全一致的一套環境,通過流量控制,只有個別城市的流量會落到此叢集,叢集內流量閉環。
-
灰度釋出: 將釋出過程分為預覽叢集、灰度城市叢集、10%流量、50%流量、100%流量的釋出機制,確保安全上線過程。
-
全鏈路壓測: 在不影響線上服務的前提下,對生產環境進行壓力測試的解決方案。用以摸清生產環境的容量、瓶頸點等。
-
機房多活: 通過多機房部署,當一個機房出現故障時,可以快速將流量切到其他機房,以減少損失。涉及流量路由、流量閉環、資料同步、資料一致性、災難應對等諸多環節的整套解決方案。
2. 穩定性規範
穩定性設計
- 【強制】呼叫方必須設定超時時間,且呼叫鏈路超時從上往下遞減,建議超時時間設定如下:
- 【強制】核心流程新增依賴預設為弱依賴,如需新增強依賴,需要經過評審決議;
- 【強制】下游服務如提供服務發現,所有服務必須通過服務發現訪問該服務,方便服務發現控制下游節點和超時時間;
- 【強制】所有內部服務必須接入服務發現,外部服務儘量推動接入服務發現;
- 【建議】建議框架支援依賴服務手動一鍵熔斷;
- 【建議】服務設計優先考慮無狀態設計;
- 【建議】寫介面建議考慮防重入;
- 【建議】系統設計原則簡單可靠,優先使用成熟技術;
- 【建議】核心服務強制,其他建議,介面建議設定合理的限流配置。
部署和運維
- 【強制】嚴禁在臨時指令碼中未通過介面或封裝方法,直接操作線上資料,如有需要,必須經過QA測試;
- 【強制】服務上線必須通過上線平臺,並接入質量平臺(功能包括自動化case、核心曲線圖及其他上線checklist),強制停留觀察’
- 【強制】一級服務需要包含預覽叢集、小流量叢集(除部分特殊服務)並且雙機房部署;
- 【建議】非一級線上服務建議包含預覽叢集;
- 【建議】新服務上線建議進行容量規劃,建議通過介面壓測或全流量壓測驗證模組容量。
監控告警
- 【強制】線上服務機器必須有基礎監控報警,包含CPU、IO、記憶體、磁碟、coredump、埠;
- 【強制】線上服務必須有基礎的服務監控,包括介面qps、fatal數量、耗時;
- 【建議】核心業務指標(發單量、搶單量、支付量等)必須有監控和報警;
- 【建議】需要有服務整體大盤,能夠涵蓋該方向核心模組監控,方便快速定位服務問題。
變更管理
- 【強制】任何一級服務變更,均需要走灰度釋出機制;
- 【強制】任何一級服務變更,包括服務變更、配置變更,均需要有相應的回滾預案,保證變更異常時可以快速回退;
- 【建議】儘量避免程式碼搭車上線;
- 【建議】服務回滾時建議同時回滾相應的程式碼和配置,保證主線程式碼的正確性;
- 【建議】配置變更,特別是複雜的配置變更時,建議增加相應的配置校驗機制。
預案管理
- 【強制】必須有多活切流預案,且需要保障有效性,必須定期組織演練,建議1月1次;
- 【強制】全鏈路壓測通道需要保證有效性,定期組織壓測;
- 【強制】一鍵限流預案需要保障有效性,定期review和演練;
- 【強制】強依賴降級預案需要保障有效性,定期演練。
故障處理原則
- 【強制】線上出現故障時,必須第一優先順序進行處理;
- 【強制】線上出現故障時,如果有變更,第一時間回滾;
- 【強制】線上出現故障,必須組織覆盤;
- 【強制】需要有覆盤規範,覆盤按照規範執行。
3. 穩定性反模式
本章節主要是基於大量的線上故障case,以具體例項驅動,加上研發全流程中各個環節容易犯的一些穩定性問題,提取一些反模式出來,供大家參考,儘量避免後續的工作中犯同樣的問題,提高線上服務的穩定性。
3.1.容災和容錯設計
**反模式3.1.1 **
過度的節點熔斷策略
【例項】
為了提高請求成功率,在下游故障時對下游節點採取熔斷措施,比如1分鐘內連續出現5次訪問出錯,則將該節點熔斷,不再呼叫(過一段時間後再恢復),某天網路抖動,下游服務4個例項中的3個均進入熔斷模式,導致訪問下游的所有流量均落到剩餘的這個例項上,壓力過大,將該例項壓垮。下游服務雪崩,整個系統不可用。
【解決方案】
熔斷模式下,還需要有熔斷保護措施,避免過度熔斷帶來的穩定性問題。
反模式3.1.2
固定的重試序列
【例項】
每次重試序列都為“下一臺”。
【後果】
一個是雪崩:假設某一類 query 的重試序列為A B,當 A 出現故障時,B 要承受兩倍的壓力,如果 B 扛不住,那麼 B 的下一個也會被壓垮;一個是上線損失流量:假設重試次數是2,上線時如果 A 和 B 同時重啟,那麼重試序列為 A B的 query 必然無結果。
【解決方案】
評估新的重試演算法,比如隨機重試。不過相對於固定的重試序列,隨機重試序列也可能給系統帶來風險,例如可能會降低下游模組的cache命中率,降低系統效能。
反模式3.1.3
不合理的超時設定
【例項】
上游服務超時時間設定不合理,下游出現問題時,直接把上游服務拖垮。
【解決方案】
應該根據鏈路的99分位耗時來設定超時時間,同時定期對鏈路的通訊相關配置進行review。
反模式3.1.4
未考慮同一請求中多次呼叫下游的影響
【例項】
服務呼叫下游時超時時間設定沒有問題,但同一請求中會序列多次呼叫某個下游服務,下游服務故障時,也會把上游服務直接拖垮。
【解決方案】
除了考慮對下游服務的單次超時,還需要考慮對下游服務的總體超時。
反模式3.1.5
不合理的重試邏輯
【例項】
整條鏈路多個地方有重試,下游服務故障時,重試被放大,導致服務雪崩。
【解決方案】
評估重試機制,梳理請求處理的整個鏈路,保證重試收斂在一個地方。
反模式3.1.6
沒有考慮到業務毛刺的影響
【例項】
某業務形態有個特點,在半點和整點時刻有請求尖刺,某次受節假日影響,訪問下游的流量瞬間暴增,導致下游服務雪崩。
【解決方案】
對業務尖刺進行平衡處理,減少對下游服務的峰值流量衝擊。
反模式3.1.7
沒有對異常輸入進行容錯處理
【例項】
業務沒有對異常輸入進行容錯處理,仍然按照正常邏輯處理,導致資料混亂。
【解決方案】
業務特別是業務入口,必須對不合理的異常輸入進行容錯處理,保證整個系統的健壯性。
反模式3.1.8
介面不支援冪等性設計
【例項】
介面不支援冪等性,網路故障時引發大量的重試,導致核心資料大量出錯。
【解決方案】
介面設計的時候就需要考慮冪等性的需求。
反模式3.1.9
沒有對非核心流程弱依賴化
【例項】
沒有對流程進行弱依賴化,導致系統整體上比較脆弱,每個依賴單元故障都會導致整個業務癱瘓。
【解決方案】
定期對系統的流程進行梳理,最小系統化,非必須流程儘量弱依賴化。
反模式3.1.10
沒有考慮ID溢位的影響
【例項】
某ID使用int32,超出後ID溢位,匯出服務異常。
【解決方案】
增加資源相關的ID欄位時要考慮ID的範圍,是否有溢位風險
定期對資源相關的ID欄位進行review,提前預防,最大限度防止故障的發生
3.2.部署和運維
反模式3.2.1
部署時未考慮網段因素
【例項】
服務部署時未考慮網段因素,服務的多個例項都部署到一個交換機下,導致交換機故障時,服務的多個例項不可用,服務所在叢集雪崩
【解決方案】
服務部署時儘量多考慮地理因素,同一服務的多個例項儘可能部署到不同的機房、交換機和網段下
反模式3.2.2
服務混部時未做好資源隔離
【例項】
多個服務混部,其中一個CPU佔用過高,導致其他服務異常
【解決方案】
多個服務混部的情況下,一定要做好資源隔離,避免因一個服務佔用資源過高,導致同一臺機器上的其他服務不可用
反模式3.2.3
沒有做到對核心業務和隔離和保護
【例項】
某非核心流程由於bug向mq寫入大量訊息,導致整個mq叢集不可用,整個業務故障
【解決方案】
核心鏈路和非核心鏈路的mq隔離,分開部署,非核心流程的變化不會影響主流程,保證核心流程和業務的穩定性
3.3.容量管理
反模式3.3.1
容量規劃時未考慮故障因素
【例項】
線上某服務qps不大,只部署了2個例項,一個例項高峰期出問題時,流量都落到另外一個例項上面,把服務壓垮
【解決方案】
容量估計時需要考慮容災因素,預留一定的buffer
如果覺得部署例項多,會浪費機器,可以考慮使用彈性雲,比較靈活
反模式3.3.2
上線新功能未合理進行容量規劃
【例項】
某服務,下游依賴眾多,在進行容量規劃時,重點都集中在某一依賴服務,未對全域性所有依賴方進行全面評估,當其中某一依賴服務出現問題,導致整體服務不可用
【解決方案】
上線新功能時,需要對所有下游依賴服務進行容量規劃,防止出現瓶頸點
3.4.變更管理
反模式3.4.1
程式碼搭車上線
【例項】
由於缺乏有效的程式碼修改管理機制,某產品線由於程式碼搭車上線,出現過多次線上故障
並且由於變更時涉及的修改比較多,導致問題定位和追查時非常困難
【解決方案】
建立嚴格的程式碼管理機制,嚴禁程式碼搭車上線,保證任何時刻主幹沒有未上線驗證的程式碼
反模式3.4.2
服務回滾時遺漏回滾程式碼
【例項】
上線出現問題,服務回滾後沒有第一時間把程式碼回滾掉。第二天其他同學上線時將未回滾的問題程式碼再次帶上線,上線時導致連續兩天出現系統故障
【解決方案】
服務回滾的時候同時第一時間回滾程式碼
反模式3.4.3
過高的併發部署設定
【例項】
部署配置的併發個數太高,導致同一時刻只有少數機器可用,引發叢集雪崩
【解決方案】
服務部署配置的併發個數,要保證剩餘機器能夠承載業務全部流量
反模式3.4.4
服務啟動或回滾時間過長
【例項】
服務上線異常,回滾時單個服務回滾時間太長,導致未能短時間內快速止損
【解決方案】
定期檢查服務的啟動和回滾時間,保證出現故障時可以第一時間完成回滾操作
反模式3.4.5
配置檔案缺少有效的校驗機制
【例項】
配置檔案由模型產出,資料配送系統實時配送到線上服務,模型產生的配置檔案有問題,引發線上故障
【解決方案】
針對配置檔案,尤其是模型產出的配置檔案,建立嚴格的檢查和校驗機制
反模式3.4.6
配置變更沒有灰度
【例項】
配置相關修改,穩定性意識上重視度不夠,沒有進行足夠的觀察和灰度,導致故障
【解決方案】
所有變更,包括服務變更、配置變更、資料變更以及環境變更,都需要進行嚴格的觀察和灰度,保證變更的質量
反模式3.4.7
變更沒有經過嚴格的測試
【例項】
變更較小,感覺沒有必要進行測試,結果出現低階錯誤,導致故障
【解決方案】
任何變更都要測試、double check,修改一行程式碼,也可能導致線上的穩定性故障
反模式3.4.8
變更時沒有嚴格按照變更規範執行
【例項】
上線時,小流量和A機房均嚴格按照規範檢查,服務和各種曲線沒有問題,上線B機房時沒有進行檢查。結果B機房出現故障。
經排查是因為B機房配置缺失
【解決方案】
任何變更都要嚴格按照變更規範嚴格檢查,上線的每個階段都要檢查服務的各種曲線和指標
反模式3.4.9
離線直接通過sql更新db資料
【例項】
直接通過sql進行離線更新資料庫,沒有做好限流保護,導致db壓力大,線上服務訪問時出現大量超時
【解決方案】
除非特殊情況,嚴禁直接通過sql操作db資料,修改需通過介面修改,方便通過曲線觀察,也可降低直接改庫的風險;
批量修改db資料需要通報dba,經過review,確認沒有問題時才可以進行操作;
批量增改、增加資料務必做好限流措施。
3.5.監控報警
** 反模式3.5.1
缺少基礎監控**
【例項】
缺少基礎監控,導致出現故障,未能第一時間感知。
【解決方案】
梳理基礎監控checklist,定期對服務的基礎監控進行review和演練。
反模式3.5.2
缺少業務監控
【例項】
缺少業務監控,導致出現故障,未能第一時間感知。
【解決方案】
對核心流程和核心業務指標,都需要新增業務監控。
反模式3.5.3
告警閾值設定有問題
【例項】
由於業務bug導致線上大量告警,先臨時將告警閾值從20調整到200,問題修復上線後忘了改回來,就一直維持這個閾值設定,導致後續業務出問題的時候,未能第一時間報出來。
【解決方案】
儘量使用短暫遮蔽報警,而不是調高閾值。
反模式3.5.4
監控告警當前已失效
【例項】
業務迭代過快,導致監控告警資訊和業務已經不再匹配。
【解決方案】
定期對告警進行演練,保證其有效性。
重大業務迭代,需要將監控告警列入checklist。
3.6.預案管理
反模式3.6.1
上游流量異常時沒有相應的防雪崩預案
【例項】
服務上游流量突增,導致服務瞬間被壓垮,系統雪崩
【解決方案】
服務必須提前做好防雪崩預案,不然很容易導致整個系統級別的故障
反模式3.6.2
服務沒有防刷和防攻擊預案
【例項】
線上問題定位時,發現某個線上服務存在大量刷介面的現象,給線上系統的穩定性帶來很大隱患,同時造成很大的資源和成本浪費。
【解決方案】
線上服務,特別是和端互動比較多的服務,設計時就需要考慮好防刷和防攻擊策略,提前做好預案
反模式3.6.3
下游故障時沒有相應的處理預案
【例項】
下游服務故障,上游服務沒有相應的處理預案,導致被下游拖垮,因為這種情況導致的大型故障非常多
【解決方案】
下游故障,尤其是下游弱依賴服務故障,需要有相應的處理預案
反模式3.6.4
故障時預案已失效
【例項】
由於業務迭代比較快,當前對某下游已經從弱依賴變成強依賴,下游故障時,執行降級預案但業務故障並沒有恢復
【解決方案】
定期對預案進行演練,保證預案有效性
3.7.穩定性原則和意識
** 反模式3.7.1
對穩定性缺乏敬畏之心**
【例項】
以為服務出故障是正常的,對穩定性不以為然
【解決方案】
技術同學需要對程式碼、線上穩定性保持敬畏之心,不能有任何僥倖心理
一行程式碼的bug,就可能導致整個業務癱瘓掉
反模式3.7.2
故障時沒有第一時間止損
【例項】
服務出現故障時,相關同學第一時間在定位故障原因,沒有第一時間進行止損
【解決方案】
出現故障必須第一優先順序處理,第一時間止損
反模式3.7.3
使用未充分驗證過的技術和方案
【例項】
某服務使用了mq的廣播特性,該特性在公司還沒有線上上被使用過,上線後觸發mq廣播消費程式碼中的一個bug,導致mq叢集不可用的故障
【解決方案】
儘量避免使用未充分驗證過的技術和方案
如果因為某些原因必須使用,一定要有相應的兜底措施,同時控制好接入的節奏
在非關鍵服務上驗證充分後,才能應用到核心鏈路上
反模式3.7.4
使用新技術時未控制好接入節奏
【例項】
某服務使用了mq的廣播特性,在非核心服務驗證時間不夠的情況下,將此特性引入核心服務,核心服務的流量比較大,觸發mq廣播消費程式碼中的一個bug,導致mq叢集不可用的故障
【解決方案】
引入新技術時一定要控制好接入的節奏
在非關鍵服務上驗證充分後,才能應用到核心鏈路上
反模式3.7.5
穩定性改進方案未及時落實
【例項】
某服務出現故障,覆盤時制定了相應的改進措施,但是未及時有效落實;後該問題再次爆發,又一次服務故障。
【解決方案】
建立改進措施落實的有效跟蹤機制,保證改進措施的有效落實。
團隊簡介
順風車服務端團隊是由一群團結互助、樂觀正直、追求極致的小夥伴匯聚而成,致力於構建一流的安全、交易、營銷服務端技術體系,助力滴滴順風車實現“分享出行讓生活更美好”的使命 。
如果你想了解滴滴順風車優質技術分享,歡迎關注「滴滴順風車技術」公眾號,閱讀原文與更多技術乾貨。
歡迎關注滴滴技術公眾號!
本文由部落格群發一文多發等運營工具平臺 OpenWrite 釋出