1. 程式人生 > >億級流量架構之服務降級思路與方法

億級流量架構之服務降級思路與方法

## 什麼是服務降級 如果看過我前面對[服務限流](https://www.cnblogs.com/Courage129/p/14423707.html)的分析,理解服務降級就很容易了,對於一個景區,平時隨便進出,但是一到春節或者十一國慶這種情況客流量激增,那麼景區會限制同時進去的人數,這叫限流,那麼什麼是服務降級呢? 簡單來說就是,將一些不太重要的景區專案砍掉,平時就那麼三五八個人,景區可以開放湖中游泳啦,摸魚啦,捉蝦啦,有情況工作人員可以下湖撈你,但是現在客流量大了,工作人員關注不過來,都在湖裡晃盪萬一沉了不太安全,大手一揮,這個專案砍了,將工作人員分配在其他地方。 在網際網路中也有類似的降級措施,像之前雙11, 有段時間是隻允許下單不允許退單或者改單,這樣做目的是什麼呢? 還是為了保證服務的可用性,當硬體軟體優化到一定的程度還是有上限,這時候將資源重點傾斜給核心業務,那些不太重要的就砍掉,保證服務的可用性。 ## 服務等級定義 服務等級定義 SLA(Service Level Agreement)是判定壓測是否異常的重要依據。壓測過程中,通過監控核心服務狀態的 SLA 指標資料,可以更直觀地瞭解壓測業務的狀態。 SLA則是服務商與您達成的正常執行時間保證。 關於這個的詳細解釋,可以參考阿里雲的介紹:[服務等級定義SLA](https://help.aliyun.com/document_detail/111729.html?spm=a2c4g.11186623.3.3.19693e74AnPY9O),這兒不過多描述,SLA 分為網路服務和雲服務,提供商的線上保證率通常要求達到6個9。 ### 6個9含義 6個9指99.9999%,也就是一個服務有99.9999%概率是安全的,6個9有多安全呢? 2個9 = (1-99%)X24 X 365 = 87.6 小時 = 3.65天 3個9 = (1-99.9%)X24 X 365 = 8.76 小時 4個9 = (1-99.99%)X24 X 365 = 0.876 小時 = 52.56分鐘 5個9 = (1-99.999%)X24 X 365 = 0.0876 小時 = 5.256分鐘 6個9 = (1-99.9999%)X24 X 365 = 0.00876 小時 = 0.5256分鐘 = 31秒 也就是,一年當中,6個9的安全性最多會有31s服務是不可用,相對來說是極高的。 ## 降級處理 ### 兜底資料 這方面有很多例子,比如某些頁面掛了會返回尋親子網。可以對一些關鍵資料設定一些兜底資料,例如設定預設值、靜態值、設定快取等。 **預設值**: 設定安全的預設值,不會引起資料問題的值,比如庫存為0 **靜態值**:請求的頁面或api無法返回資料,提供一套靜態資料展示,比如載入失敗提示重試,或者尋親子網,或者跳到預設選單,給使用者一個稍微好一點的體驗。 **快取**: 快取無法更新便使用舊的快取 ## 限流降級 限流顧名思義,提前對各個型別的請求設定最高的QPS閾值,若高於設定的閾值則對該請求直接返回,不再呼叫後續資源,也就是當流量洪峰到達的時候,可能需要丟棄一部分使用者來保證服務可用性,對於丟棄的使用者可以提供友好的提示,比如提示使用者當前繁忙、稍後重試等。 限流需要結合壓測等,瞭解系統的最高水位,也是在實際開發中應用最多的一種穩定性保障手段。當伺服器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放伺服器資源以保證核心任務的正常執行。 ## 超時降級 對呼叫的資料設定超時時間,當呼叫失敗時,對服務降級,舉個例子,當訪問資料已經超時了,且這個業務不是核心業務,可以在超時之後進行降級,比如商品詳情頁上有推薦內容或者評價,但是可以降級顯示評價暫時不顯示,這對主要的使用者功能——購物,不產生影響,如果是遠端呼叫,則可以商量一個雙方都可以接受的最大響應時間,超時則自動降級。 ## 故障降級 如果遠端呼叫的伺服器掛了(網路故障、DNS故障、HTTP服務返回錯誤),則可以進行降級, 例如返回預設值或者兜底資料或者靜態頁面,也可以返回之前的快取資料。 ### 重試/自動處理 客戶端高可用:提供多個可呼叫的服務地址,這樣做 微服務重試:dubbo重試機制 API呼叫重試:當達到重試次數後,增加訪問標記,服務降級,非同步探測服務是否恢復。 WEB端:在服務不可用時,web端增加重試按鈕或自動重試可以提供更友好的體驗。 自動重試需設定重試次數和資料冪等處理 ## 降級開關 在伺服器提供支援期間, 如果監控到線上一些服務存在問題,這個時候需要暫時將這些服務去掉,有時候通過服務呼叫一些服務,但是服務依賴的資料庫可能存在,網絡卡被打滿了,資料庫掛了,很多慢查詢等等,此時要做的就是暫停相關的系統服務,也就是人工使用開關降級。開關可以放在某地,定期同步開關資料,通過判斷開關值來決定是否做出降級。 開關降級還有一個作用,例如新的服務版本剛開發處在灰度測試階段,不太確定裡面的邏輯等等是否正確,如果有問題應該可以根據開關的值切回舊的版本。 在服務呼叫方設定一個flag,標記服務是否可用,另外key可以儲存儲存在在本地,也可以儲存在第三方的配置檔案中,例如資料庫、redis、zookeeper中。 ### 爬蟲和機器人 分析機器人行為:短時間連續操作,agent,行為軌跡、拖拽(模擬登陸/秒殺/灌水) 爬蟲:引到到靜態頁或快取頁 ### 讀降級 簡而言之,在一個請求內,多級快取架構下,後端快取或db不可用,可以使用前端快取或兜底資料讓使用者體驗好一點。 對於讀服務降級一般採用的策略有: **暫時切換讀**: 降級到讀快取、降級到走靜態化 **暫時遮蔽讀**: 遮蔽讀入口、遮蔽某個讀服務 通常讀的流程為: **接入層快取→應用層本地快取→分散式快取→RPC服務/DB** 我們會在接入層、應用層設定開關,當分散式快取、RPC服務/DB有問題時自動降級為不呼叫。當然這種情況適用於對讀一致性要求不高的場景。 頁面降級、頁面片段降級、頁面非同步請求降級都是讀服務降級,目的是丟卒保帥,保護核心執行緒,或者因資料問題暫時遮蔽。 還有一種是頁面靜態化場景。 **動態化降級為靜態化**:比如,平時網站可以走動態化渲染商品詳情頁,但是,到了大促來臨之際可以將其切換為靜態化來減少對核心資源的佔用,而且可以提升效能。其他還有如列表頁、首頁、頻道頁都可以這麼處理。可以通過一個程式定期推送靜態頁到快取或者生成到磁碟,出問題時直接切過去。 **靜態化降級為動態化**:比如,當使用靜態化來實現商品詳情頁架構時,平時使用靜態化來提供服務,但是,因為特殊原因靜態化頁面有問題了,需要暫時切換回動態化來保證服務正確性。 以上都保證了出問題時有預案,使用者可以繼續使用網站,不影響使用者購物體驗。 ### 寫降級 大家都知道硬碟效能比不上記憶體效能,如果訪問量很高的話,資料庫頻繁讀寫可能撐不住,那麼怎麼辦呢,可以讓記憶體(假如是Redis)庫來暫時滿足寫任務,同時將執行的指令記錄下來,然後將這個資訊傳送到資料庫,也就是不在追求記憶體與資料庫資料的強一致性,只要資料庫資料與Redis資料庫中的資訊滿足最終話一致性即可。 也就是說,正常情況下可以同步扣減庫存,在效能扛不住時,降級為非同步。另外,如果是秒殺場景可以直接降級為非同步,從而保護系統。還有,如下單操作可以在大促時暫時降級,將下單資料寫入Redis,然後等峰值過去了再同步回DB,當然也有更好的解決方案,但是更復雜,不是本篇的重點。 還有如使用者評價,如果評價量太大,那麼也可以把評價從同步寫降級為非同步寫。當然也可以對評價按鈕進行按比例開放(比如,一些人看不到評價操作按鈕)。比如,評價成功後會發一些獎勵,在必要的時候降級同步到非同步。 **總結** 在cap原理和BASE理論中寫操作存在於**資料一致性**這個環節,降級的目的是為了提供高可用性,在多數的網際網路架構中,可用性是大於資料一致性的。所以喪失寫入資料同步,通過上面的理論,我們也能勉強接受資料最終一致性。高併發場景下,寫入操作無法及時到達或抗壓,可以非同步消費資料/cache更新/log等方式 ## 前端降級 當系統出現問題的時候,儘量將請求隔離在離使用者最近的位置,避免無效鏈路訪問, 在後端服務部分或完全不可用的時候,可以使用本地快取或兜底資料,在一些特殊場景下,對資料一致性要求不高的時候,比如秒殺、抽獎等可以做假資料。 #### JS降級 在js中埋降級開關,在訪問不到達,系統閾值的時候可以避免傳送請求 主要控制頁面功能的降級,在頁面中,通過JS指令碼部署功能降級開關,在適當時機開啟/關閉開關。 #### 接入層降級 可以在接入層,在使用者請求還沒到達服務的時候,通過、Nginx + Lua、Haproxy + lua過濾無效請求達到服務降級的目的, 主要控制請求入口的降級,請求進入後,會首先進入接入層,在接入層可以配置功能降級開關,可以根據實際情況進行自動/人工降級。這個可以參考第17章,尤其在後端應用服務出問題時,通過接入層降級從而給應用服務有足夠的時間恢復服務。 #### 應用層降級 主要控制業務的降級,在應用中配置相應的功能開關,根據實際業務情況進行自動/人工降級。 SpringCloud中可以通過Hystrix配置中心可以進行人工降級,也可以根據服務的超時時間進行自動降級, Hystrix是Netflix開源的一款針對分散式系統的延遲和容錯庫,目的是用來隔離分散式服務故障。它提供執行緒和訊號量隔離,以減少不同服務之間資源競爭帶來的相互影響;官網講Hystrix提供優雅降級機制;提供熔斷機制使得服務可以快速失敗,而不是一直阻塞等待服務響應,並能從中快速恢復。Hystrix通過這些機制來阻止級聯失敗並保證系統彈性、可用。下圖是一個典型的分散式服務實現。 ![](https://img2020.cnblogs.com/blog/2002319/202102/2002319-20210221202135362-626713658.png) ## 片段降級 例如開啟淘寶首頁,這一瞬間需要載入很多資料,有靜態的例如圖片、CSS、JS等,也有很多其他商品等等,這麼多資料中,如果一部分沒有請求到,那麼就可以片段降級,意思是就不載入這些資料了,用其他資料頂替,例如其他商品資訊或者等等。 ## 提前預埋 這個很容易理解,大家應該都記得,每次雙十一之前,淘寶總會提醒你下載更新,按道理來講,活動還沒開始,更新啥呢? 做法是對於一部分靜態資料可以提前更新到你手機上,當你雙十一時就不用再遠端連線伺服器載入了,避免了消耗網路