從0開始學微服務:20 服務端出現故障時該如何應對?

在專欄前面我講過,單體應用改造成微服務的一個好處是可以減少故障影響範圍,故障被侷限在一個微服務系統本身,而不是整個單體應用都崩潰。那麼具體到一個微服務系統,如果出現了故障,應該如何處理呢?

首先,我先來帶你回顧一下微服務系統可能出現故障的種類,主要有三種故障。

集羣故障。根據我的經驗,微服務系統一般都是集羣部署的,根據業務量大小而定,集羣規模從幾臺到甚至上萬臺都有可能。一旦某些代碼出現 bug,可能整個集羣都會發生故障,不能提供對外提供服務。單 IDC 故障。現在大多數互聯網公司爲了保證業務的高可用性,往往業務部署在不止一個 IDC。然而現實中時常會發生某個 IDC 的光纜因爲道路施工被挖斷,導致整個 IDC 脫網。單機故障。顧名思義就是集羣中的個別機器出現故障,這種情況往往對全局沒有太大影響,但會導致調用到故障機器上的請求都失敗,影響整個系統的成功率。

在我的實踐過程中,這三種故障都經常遇到,因此相應的處理手段也可謂駕輕就熟,下面就把我應對故障的實戰經驗分享給你,希望對你有所幫助。

集羣故障

一般而言,集羣故障的產生原因不外乎有兩種:一種是代碼 bug 所導致,比如說某一段 Java 代碼不斷地分配大對象,但沒有及時回收導致 JVM OOM 退出;另一種是突發的流量衝擊,超出了系統的最大承載能力,比如“雙 11”這種購物活動,電商系統會在零點一瞬間湧入大量流量,超出系統的最大承載能力,一下子就把整個系統給壓垮了。

應付集羣故障的思路,主要有兩種:限流和降級.

1. 限流

顧名思義,限流就是限制流量,通常情況下,系統能夠承載的流量根據集羣規模的大小是固定的,可以稱之爲系統的最大容量。當真實流量超過了系統的最大容量後,就會導致系統響應變慢,服務調用出現大量超時,反映給用戶的感覺就是卡頓、無響應。所以,應該根據系統的最大容量,給系統設置一個閾值,超過這個閾值的請求會被自動拋棄,這樣的話可以最大限度地保證系統提供的服務正常。

除此之外,通常一個微服務系統會同時提供多個服務,每個服務在同一時刻的請求量也是不同的,很可能出現的一種情況就是,系統中某個服務的請求量突增,佔用了系統中大部分資源,導致其他服務沒有資源可用。因此,還要針對系統中每個服務的請求量也設置一個閾值,超過這個閾值的請求也要被自動拋棄,這樣的話不至於因爲一個服務影響了其他所有服務。

在實際項目中,可以用兩個指標來衡量服務的請求量,一個是 QPS 即每秒請求量,一個是工作線程數。不過 QPS 因爲不同服務的響應快慢不同,所以系統能夠承載的 QPS 相差很大,因此一般選擇工作線程數來作爲限流的指標,給系統設置一個總的最大工作線程數以及單個服務的最大工作線程數,這樣的話無論是系統的總請求量過大導致整體工作線程數量達到最大工作線程數,還是某個服務的請求量超過單個服務的最大工作線程數,都會被限流,以起到保護整個系統的作用。

2. 降級

什麼是降級呢?在我看來,降級就是通過停止系統中的某些功能,來保證系統整體的可用性。降級可以說是一種被動防禦的措施,爲什麼這麼說呢?因爲它一般是系統已經出現故障後所採取的一種止損措施。

那麼降級一般是如何實現的呢?根據我的實踐來看, 一種可行的方案是通過開關來實現。

具體來講,就是在系統運行的內存中開闢一塊區域,專門用於存儲開關的狀態,也就是開啓還是關閉。並且需要監聽某個端口,通過這個端口可以向系統下發命令,來改變內存中開關的狀態。當開關開啓時,業務的某一段邏輯就不再執行,而正常情況下,開關是關閉的狀態。

開關一般用在兩種地方,一種是新增的業務邏輯,因爲新增的業務邏輯相對來說不成熟,往往具備一定的風險,所以需要加開關來控制新業務邏輯是否執行;另一種是依賴的服務或資源,因爲依賴的服務或者資源不總是可靠的,所以最好是有開關能夠控制是否對依賴服務或資源發起調用,來保證即使依賴出現問題,也能通過降級來避免影響。

在實際業務應用的時候,降級要按照對業務的影響程度進行分級,一般分爲三級:一級降級是對業務影響最小的降級,在故障的情況下,首先執行一級降級,所以一級降級也可以設置成自動降級,不需要人爲干預;二級降級是對業務有一定影響的降級,在故障的情況下,如果一級降級起不到多大作用的時候,可以人爲採取措施,執行二級降級;三級降級是對業務有較大影響的降級,這種降級要麼是對商業收入有重大影響,要麼是對用戶體驗有重大影響,所以操作起來要非常謹慎,不在最後時刻一般不予採用。

單 IDC 故障

在現實情況下,整個 IDC 脫網的事情時有發生,多半是因爲不可抗力比如機房着火、光纜被挖斷等,如果業務全部部署在這個 IDC,那就完全不可訪問了,所以國內大部分的互聯網業務多采用多 IDC 部署。具體來說,有的採用同城雙活,也就是在一個城市的兩個 IDC 內部署;有的採用異地多活,一般是在兩個城市的兩個 IDC 內部署;當然也有支付寶這種金融級別的應用採用了“三地五中心”部署,這種部署成本顯然高比兩個 IDC 要高得多,但可用性的保障要更高。

採用多 IDC 部署的最大好處就是當有一個 IDC 發生故障時,可以把原來訪問故障 IDC 的流量切換到正常的 IDC,來保證業務的正常訪問。

流量切換的方式一般有兩種,一種是基於 DNS 解析的流量切換,一種是基於 RPC 分組的流量切換。

1. 基於 DNS 解析的流量切換

基於 DNS 解析流量的切換,一般是通過把請求訪問域名解析的 VIP 從一個 IDC 切換到另外一個 IDC。比如訪問“www.weibo.com”,正常情況下北方用戶會解析到聯通機房的 VIP,南方用戶會解析到電信機房的 VIP,如果聯通機房發生故障的話,會把北方用戶訪問也解析到電信機房的 VIP,只不過此時網絡延遲可能會變長。

2. 基於 RPC 分組的流量切換

對於一個服務來說,如果是部署在多個 IDC 的話,一般每個 IDC 就是一個分組。假如一個 IDC 出現故障,那麼原先路由到這個分組的流量,就可以通過向配置中心下發命令,把原先路由到這個分組的流量全部切換到別的分組,這樣的話就可以切換故障 IDC 的流量了。

單機故障

單機故障是發生概率最高的一種故障了,尤其對於業務量大的互聯網應用來說,上萬臺機器的規模也是很常見的。這種情況下,發生單機故障的概率就很高了,這個時候只靠運維人肉處理顯然不可行,所以就要求有某種手段來自動處理單機故障。

根據我的經驗,處理單機故障一個有效的辦法就是自動重啓。具體來講,你可以設置一個閾值,比如以某個接口的平均耗時爲準,當監控單機上某個接口的平均耗時超過一定閾值時,就認爲這臺機器有問題,這個時候就需要把有問題的機器從線上集羣中摘除掉,然後在重啓服務後,重新加入到集羣中。

不過這裏要注意的是,需要防止網絡抖動造成的接口超時從而觸發自動重啓。一種方法是在收集單機接口耗時數據時,多采集幾個點,比如每 10s 採集一個點,採集 5 個點,當 5 個點中有超過 3 個點的數據都超過設定的閾值範圍,才認爲是真正的單機問題,這時會觸發自動重啓策略。

除此之外,爲了防止某些特殊情況下,短時間內被重啓的單機過多,造成整個服務池可用節點數太少,最好是設置一個可重啓的單機數量佔整個集羣的最大比例,一般這個比例不要超過 10%,因爲正常情況下,不大可能有超過 10% 的單機都出現故障。

總結

今天我們探討了微服務系統可能出現的三種故障:集羣故障、單 IDC 故障、單機故障,並且針對這三種故障我給出了分別的解決方案,包括降級、限流、流量切換以及自動重啓。

在遇到實際的故障時,往往多個手段是並用的,比如在出現單 IDC 故障,首先要快速切換流量到正常的 IDC,但此時可能正常 IDC 並不足以支撐兩個 IDC 的流量,所以這個時候首先要降級部分功能,保證正常的 IDC 順利支撐切換過來的流量。

而且要儘量讓故障處理自動化,這樣可以大大減少故障影響的時間。因爲一旦需要引入人爲干預,往往故障處理的時間都得是 10 分鐘以上,這對大部分用戶敏感型業務的影響是巨大的,如果能做到自動化故障處理的話,可以將故障處理的時間降低到 1 分鐘以內甚至秒級別,這樣的話對於用戶的影響最小。

思考題

上面我提到爲了避免單 IDC 故障導致服務不可用情況的發生,服務需要採用多 IDC 部署,這個時候就要求服務依賴的數據也需要存儲在多個 IDC 內,這樣勢必會帶來數據一致性的問題,你有什麼解決方案嗎?

歡迎你在留言區寫下自己的思考,與我一起討論。

相關文章