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

什麼是服務降級


如果看過我前面對服務限流的分析, 理解服務降級就很容易了, 對於一個景區, 平時隨便進出, 但是一到春節或者十一國慶這種情況客流量激增, 那麼景區會限制同時進去的人數, 這叫限流, 那麼什麼是服務降級呢?

簡單來說就是, 將一些不太重要的景區項目砍掉, 平時就那麼三五八個人, 景區可以開放湖中游泳啦, 摸魚啦, 捉蝦啦, 有情況工作人員可以下湖撈你, 但是現在客流量大了, 工作人員關注不過來, 都在湖裏晃盪萬一沉了不太安全, 大手一揮, 這個項目砍了, 將工作人員分配在其他地方。

在互聯網中也有類似的降級措施, 像之前雙 11, 有段時間是隻允許下單不允許退單或者改單, 這樣做目的是什麼呢?

還是爲了保證服務的可用性, 當硬件軟件優化到一定的程度還是有上限, 這時候將資源重點傾斜給核心業務, 那些不太重要的就砍掉, 保證服務的可用性。

服務等級定義

服務等級定義 SLA(Service Level Agreement)是判定壓測是否異常的重要依據。壓測過程中,通過監控核心服務狀態的 SLA 指標數據,可以更直觀地瞭解壓測業務的狀態。

SLA 則是服務商與您達成的正常運行時間保證。

關於這個的詳細解釋, 可以參考阿里雲的介紹: 服務等級定義 SLA(https://help.aliyun.com/document_detail/111729.html), 這兒不過多描述, 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 通過這些機制來阻止級聯失敗並保證系統彈性、可用。下圖是一個典型的分佈式服務實現。

片段降級

例如打開淘寶首頁, 這一瞬間需要加載很多數據, 有靜態的例如圖片、CSS、JS 等, 也有很多其他商品等等, 這麼多數據中, 如果一部分沒有請求到, 那麼就可以片段降級, 意思是就不加載這些數據了, 用其他數據頂替, 例如其他商品信息或者等等。

提前預埋

這個很容易理解, 大家應該都記得, 每次雙十一之前, 淘寶總會提醒你下載更新, 按道理來講, 活動還沒開始, 更新啥呢?

做法是對於一部分靜態數據可以提前更新到你手機上, 當你雙十一時就不用再遠程連接服務器加載了, 避免了消耗網絡資源。

作者:等不到的口琴

來源:www.cnblogs.com/Courage129/p/14427020.html

架構師

我們都是架構師!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/hAH4DaBdBW_OXUB8pciKtg