億級 QPS 微信後臺是如何熔斷降級,防止崩潰的?
微信作爲月活用戶超過 13 億的國民級應用,每天處理的請求量簡直可以用 “天文數字” 來形容。 想象一下,微信後臺每秒要應對數億次用戶請求——聊天、朋友圈刷屏、微信支付、甚至紅包雨。
這麼大的流量衝擊下,系統稍有不慎,可能就會 “崩了”。可事實是,微信後臺一直穩得讓人驚訝。那麼問題來了,微信是怎麼做到面對億級 QPS 的併發請求時,還能穩如泰山、不崩不垮的?
答案就是熔斷、降級和限流
這些機制就像我們給系統裝上的 “保險絲”,當壓力過大或者某個服務出問題時,它會主動切斷,避免讓整個系統拖垮。
爲了避免過載,微信後臺在服務繁忙時,會優先保障核心功能,比如保證你聊天消息正常發送,朋友圈可能加載慢點,甚至某些非核心功能可能被臨時關閉。通過這些手段,微信才能在巨大的流量衝擊下保持穩定。
今天,我們就以上述問題背景仔細聊聊,如何通過這些技術手段,在億級 QPS 的場景中做到 “泰然自若” 的。
降級保護的基本原理
什麼是降級保護?
在高併發的場景下,降級其實是一種保護系統的 “聰明” 策略,目的很簡單:
當系統遇到高壓力或某個功能故障時,主動關閉或減弱一些不太重要的功能,保證關鍵功能依然可用。
降級其實就像我們在工作中常遇到的 “輕重緩急” 法則,當你手頭工作特別多時,必須先做最重要的任務,其他可以先放一放。微信後臺的降級保護就是在高流量和服務異常的情況下,通過合理的策略來保證系統不至於崩潰。
2. 降級保護的幾個核心策略
2.1 資源隔離
資源隔離的核心思想是:
不同的服務之間應該獨立運行,互不干擾。
就像我們在公司不同的項目組之間,如果一個組出問題了,不會影響其他組的正常運作。同樣,在微信後臺,服務之間會被隔離開,保證某個模塊出現問題時,不會連累整個系統。
2.2 限流降級
限流就像是給水龍頭加個閥門,當流量過大時,系統自動 “限速”,防止瞬時的高流量沖垮系統。系統在面對突如其來的高流量時,會先控制流量,確保系統不會超負荷工作。
2.3 超時降級
在超時降級策略中,如果某個服務響應超時,系統會自動跳過該服務,避免長期等待拖慢整體流程。就像你在工作中等待某個部門提供資料,超過了約定的時間,就不再等,先進行後續步驟。
2.4 故障降級
故障降級策略是當某個模塊或服務徹底掛掉時,主動關閉或者部分功能停用,防止故障擴大。就像某個部門全員休假,臨時關閉該業務模塊,等他們回來再恢復正常運行。
2.5 失敗次數降級
微信後臺會對某些服務的調用失敗率進行監控,當失敗次數超過預定閾值後,自動觸發降級,防止系統因反覆失敗操作而崩潰。就像你嘗試同一個工作任務多次失敗後,會暫時放棄,去處理別的事情,避免浪費時間。
2.6 熔斷降級
熔斷降級有點類似於家裏的電路保險絲,當某個服務故障頻繁,系統會切斷對該服務的調用,避免該服務拖垮整個系統。
這個策略防止一個環節的問題連累全局。想象一下,如果公司一個系統模塊頻繁崩潰,那麼技術團隊會果斷停止該模塊的使用,防止影響其他業務。
2.7 分層分級細粒高精度降級
微信的系統複雜龐大,因此降級並不是 “一刀切”,而是分層分級的。不同的用戶、不同的業務模塊都有不同的優先級,系統會根據這些優先級進行差異化的降級處理。
比如,在高峯期,微信可能會優先保證 VIP 用戶、企業用戶的服務穩定性,普通用戶則可能體驗到一些延遲。同時,微信會對不同業務模塊根據其重要性進行分級保護,聊天、支付等核心功能優先保障,非核心功能如朋友圈加載、廣告推送等可以優先降級或關閉。這種 “分層分級” 的降級方式,可以讓微信系統在面對巨量併發時,最大程度地維持關鍵業務的正常運行。
如果你近期準備面試跳槽,建議在 cxykk.com 在線刷題,涵蓋 1 萬 + 道 Java 面試題,幾乎覆蓋了所有主流技術面試題、簡歷模板、算法刷題,全部免費
降級保護的主流架構方案
在大規模分佈式微服務應用中,主流的架構方案有
-
基於 Hystrix 熔斷降級、限流降級 架構方案
-
基於 Sentinel 熔斷降級、限流降級 架構方案
1. Hystrix 是什麼?能夠幫我們做什麼?
在分佈式系統中,隨着服務越來越複雜,依賴越來越多,你可能經常會遇到某個服務掛掉或者響應特別慢的情況。如果沒有任何保護機制,問題可能會迅速擴散,一個小故障就可能導致整個系統崩潰。這時,Hystrix 就派上了用場。
Hystrix 是由 Netflix 開發的一個熔斷器工具庫,主要用來防止分佈式系統的雪崩效應。
就像你負責一個複雜的項目,每個環節都互相依賴,一旦某個小組出問題,整個項目進展就可能被拖垮。Hystrix 就像這個項目的 “保險絲”,當某個環節出問題時,它會主動切斷對該環節的調用,防止問題蔓延到其他小組,確保整個項目還能按時推進。
Hystrix 能幫我們做什麼呢?
它可以:
-
限流:當系統承受高併發流量時,自動限制請求,防止系統過載;
-
降級:如果某個服務響應變慢或者失敗,Hystrix 會自動降級,優先保障核心功能;
-
熔斷:當某個服務頻繁失敗,Hystrix 會主動 “熔斷” 該服務,避免繼續調用造成系統崩潰;
-
資源隔離:爲每個服務分配獨立的資源,防止服務之間相互影響。
通過這些手段,Hystrix 能幫我們在高併發、大規模的場景下提高系統的容錯性和穩定性。
2. Hystrix 限流降級的實現原理
Hystrix 實現限流的原理非常簡單:每個服務都有一個預先設定的最大併發量,超出這個限制後,新的請求就會被拒絕,返回一個預設的降級響應。
比如,假設你在高峯期處理訂單,如果用戶服務的併發量超過了設定的上限 (5),Hystrix 就會觸發限流機制,拒絕處理新訂單,返回一個“系統繁忙,請稍後再試” 的信息。這樣既不會讓用戶服務過載,也能防止整個系統崩潰。
在 Spring Boot 中,限流的實現非常簡單,只需要在方法上加上 @HystrixCommand 註解,並設定一個併發量的限制,超出限制時,直接觸發降級邏輯。
@Service
public class UserService {
@HystrixCommand(fallbackMethod = "getUserFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10") // 限流
})
public String getUser(String userId) {
// 模擬查詢用戶信息的耗時操作
return "User info for " + userId;
}
// 降級方法
public String getUserFallback(String userId) {
return "Default user info"; // 降級處理,返回默認值
}
}
3. Hystrix 異常降級實現及原理
在分佈式系統中,某個服務出現異常是非常常見的情況。Hystrix 的異常降級機制就是爲了解決這個問題,當某個服務調用出現異常時,Hystrix 會自動返回一個備用的降級結果,而不是讓調用卡在那裏,影響整體體驗。
Hystrix 是如何做到這一點的呢?
當你發起某個服務請求時,Hystrix 會監控這個請求,如果服務返回異常,比如超時、網絡故障等,Hystrix 就會快速捕獲這個異常,並根據預設的降級邏輯,返回一個 “降級版” 的結果。
例如:
@Service
public class PaymentService {
@HystrixCommand(fallbackMethod = "paymentFallback")
public String processPayment(String paymentId) {
// 假設這裏調用了外部支付服務,可能會拋出異常
if ("error".equals(paymentId)) {
throw new RuntimeException("Payment service failure");
}
return "Payment processed: " + paymentId;
}
// 降級處理邏輯
public String paymentFallback(String paymentId) {
return "Payment failed, please try again later."; // 返回降級信息
}
}
4. Hystrix 調用超時降級實現及原理
服務超時是分佈式系統中的常見問題,Hystrix 的超時降級機制就是爲了解決這種情況。當某個服務響應時間超過預設的閾值,Hystrix 會主動中斷該調用,並返回降級處理結果,而不是讓系統繼續等待。
它的工作原理是這樣的:每個服務調用都有一個預設的超時時間,假如這個時間是 2 秒,超過 2 秒還沒響應,Hystrix 會自動觸發超時降級,返回一個默認的結果,避免因爲單個服務的超時導致整個系統 “卡住”。
比如,假設微信創建訂單接口出現了超時問題,正常情況下你可能得等好幾秒才能得到一個超時錯誤,但 Hystrix 會提前設定一個超時閾值,比如 2 秒。如果 2 秒內沒得到響應,它會立刻給你返回一個 “訂單服務不可用” 的提示,不至於讓用戶體驗特別糟糕。
@Service
public class OrderService {
@HystrixCommand(fallbackMethod = "orderFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") // 設置超時時間爲 3 秒
})
public String createOrder(String orderId) throws InterruptedException {
// 模擬調用遠程服務,耗時操作
Thread.sleep(4000); // 超過了 3 秒的超時時間
return "Order created: " + orderId;
}
// 超時後的降級處理
public String orderFallback(String orderId) {
return "Order creation failed, please try again later.";
}
}
5. Hystrix 資源隔離實現及原理
資源隔離相當於對不同的鏈路分級對待,對非核心鏈路,本質是一種降級處理
資源隔離是 Hystrix 的另一個重要特性。
它通過爲每個服務分配獨立的線程池或信號量,確保某個服務出現問題時不會影響其他服務。
Hystrix 通過將每個服務隔離開來,爲它們分配獨立的資源。假如某個服務的線程池耗盡,它只會影響該服務的調用,而不會連累到其他服務。
比如,如果用戶查詢服務出問題了,支付服務依然可以正常運作。
Hystrix 實現資源隔離,主要有兩種技術:
-
線程池
-
信號量
默認情況下,Hystrix 使用線程池模式。
線程池隔離(艙壁模式)
線程池隔離,本質上來說,就是艙壁模式
宋朝的航海船舶製造中,最具創新性的技術之一是隔艙結構設計,也被稱爲水密隔艙。
水密隔艙將船體內部劃分爲多個獨立的艙室,每個艙室之間用堅固的隔板分隔,並且這些隔板具有水密性。這一設計意味着,即使船體某一部分破損進水,水也只能流入一個隔艙,而不會擴散到其他艙室,從而保持船隻的浮力,避免整體沉沒。
線程池隔離的思想具有異曲同工之妙。
在 RPC 調用過程中,使用艙壁模式可以保護有限的系統資源不被耗盡。在一個基於微服務的應用程序中,通常需要調用多個微服務提供者的接口才能完成一個特定任務。不使 用艙壁模式,所有的 RPC 調用都從同一個線程池中獲取線程,一個具體的實例如下圖所示。
在 java 中實現代碼也很簡答,我們只需要給 RPC 調用接口指定一個線程池即可
@Service
public class ProductService {
@HystrixCommand(fallbackMethod = "productFallback", threadPoolKey = "productThreadPool", threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"), // 線程池大小
@HystrixProperty(name = "maxQueueSize", value = "5") // 隊列長度
})
public String getProduct(String productId) {
// 模擬獲取產品信息
return "Product info for: " + productId;
}
// 降級方法
public String productFallback(String productId) {
return "Product information not available.";
}
}
除了使用線程池進行資源隔離之外,Hystrix 還可以使用信號量機制完成資源隔離。信號量所起到的作用就像一個開關,而信號量的值就是每個命令的併發執行數量,當併發數高於信號量的值時,就不再執行命令,感興趣的同學可以自己學習下。
6. Hystrix 熔斷降級實現及原理
Hystrix 的熔斷降級機制是它最出名的功能之一,它的核心原理是通過監控服務調用的失敗率,當失敗率達到一定閾值後,主動熔斷該服務的調用,防止持續失敗的服務拖累整個系統。
熔斷降級就像家裏的保險絲,如果某個電器出故障,保險絲會自動切斷電路,防止短路導致火災。同樣,Hystrix 的熔斷器會在服務頻繁失敗時,切斷對該服務的調用,並直接返回降級結果。
熔斷器的 3 種狀態如下:
-
1)closed:熔斷器關閉狀態,這也是熔斷器的初始狀態,此狀態下 RPC 調用正常放行。
-
2)open:失敗比例到一定的閾值之後,熔斷器進入開啓狀態,此狀態下 RPC 將會快速失敗,執行失敗回退邏輯。
-
3)half-open:在打開一定時間之後(睡眠窗口結束),熔斷器進入半開啓狀態,小流量嘗試進行 RPC 調用放行。如果嘗試成功則熔斷器變爲 closed 狀態,RPC 調用正常;如果嘗試失敗則熔斷器變爲 open 狀態,RPC 調用快速失敗。
熔斷器狀態之間相互轉換的邏輯關係如下圖所示。
在 SpringBoot 項目中,實現方案也很簡單
@Service
public class ShippingService {
@HystrixCommand(fallbackMethod = "shippingFallback", commandProperties = {
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"), // 熔斷閾值,5次請求失敗
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 熔斷後等待 10 秒再嘗試恢復
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50") // 錯誤率達到 50% 觸發熔斷
})
public String shipOrder(String orderId) {
if ("error".equals(orderId)) {
throw new RuntimeException("Shipping service failure");
}
return "Order shipped: " + orderId;
}
// 熔斷後的降級處理
public String shippingFallback(String orderId) {
return "Shipping service is currently unavailable.";
}
}
在這個例子中,當 shipOrder 方法的錯誤率超過 50%,並且 5 次請求中有超過一半失敗時,Hystrix 會自動熔斷該服務,10 秒後再嘗試恢復調用。如果問題依然存在,熔斷器會繼續保持 “斷開” 狀態,直到服務恢復正常。
如果你近期準備面試跳槽,建議在 cxykk.com 在線刷題,涵蓋 1 萬 + 道 Java 面試題,幾乎覆蓋了所有主流技術面試題、簡歷模板、算法刷題,全部免費
7. Sentinel 是什麼,能夠幫我們做什麼?
Sentinel 是阿里巴巴開源的流量控制框架,設計初衷就是爲了幫助開發者在高併發場景下保持系統的穩定性和高可用性。它可以通過流量控制、熔斷降級、系統負載保護等手段,動態地保護系統,避免因過載或某個服務的故障引發系統雪崩效應。
Sentinel 可以幫我們做什麼?
-
限流:限制某個接口的併發請求量,防止系統因爲流量暴增而崩潰。
-
熔斷降級:當某個服務失敗次數過多或響應時間過長時,自動觸發降級邏輯,避免繼續調用失敗服務。
-
實時監控和報警:Sentinel 提供了豐富的監控功能,可以實時查看系統的運行狀態,及時發現問題。
Sentinel 對於 Spring Boot 項目特別友好,只需要簡單配置就能集成,幫助我們快速實現服務的保護措施。
8. Sentinel 限流降級的原理及實現方式
在系統中,限流 是第一道保護牆,當系統流量超過承受範圍時,Sentinel 會通過各種限流方式來保護系統,避免被突發流量壓垮。限流的核心思想是:“寧可拒絕一部分請求,也不能讓系統整體崩潰。”
8.1 直接失敗模式限流
直接失敗模式限流的邏輯非常簡單粗暴:當流量超過設定的閾值時,Sentinel 直接拒絕多餘的請求,返回錯誤結果。類似於餐廳滿座時拒絕再接待新顧客。
代碼示例:
@RestController
public class HelloController {
@GetMapping("/hello")
@SentinelResource(value = "hello", blockHandler = "handleLimit")
public String hello() {
return "Hello, Sentinel!";
}
// 限流後的降級處理
public String handleLimit(BlockException ex) {
return "Too many requests, please try again later.";
}
}
在這個例子中,當 /hello
接口的流量超過限制時,Sentinel 會直接返回 "Too many requests"
,拒絕多餘的請求。
8.2 關聯模式限流
關聯模式限流的意思是,限流的依據並不一定是當前接口的流量,而是根據其他關聯接口的流量。比如,你可能希望根據用戶登錄的頻率來限制用戶數據查詢的併發量。
場景舉例: 當登錄請求的流量激增時,系統會自動限制其他一些耗時的查詢操作,避免讓高負載的登錄操作影響整個系統。
代碼示例:
// 假設登錄接口的流量激增,我們希望根據登錄請求限制其他操作
@RestController
public class UserController {
@GetMapping("/user/info")
@SentinelResource(value = "userInfo", blockHandler = "handleLimit")
public String getUserInfo() {
return "User info";
}
public String handleLimit(BlockException ex) {
return "System busy, please try again later.";
}
}
在這個例子中,/user/info
的訪問頻率會受到 /login
接口流量的影響,防止登錄流量激增導致其他接口過載。
8.3 Warm up(預熱)模式限流
預熱限流模式的核心是逐步提高系統的吞吐量,防止系統在高併發初期突然被流量沖垮。這就像是發動機啓動時需要預熱,不能一下子達到全速。Warm up 模式非常適合處理突發流量較大的場景。
代碼示例:
// 通過配置文件設置預熱模式
@Bean
public Converter<String, List<FlowRule>> flowRuleConverter() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("hello");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(20); // 設定閾值
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP); // 預熱模式
rule.setWarmUpPeriodSec(10); // 預熱時間 10 秒
rules.add(rule);
return new FlowRuleNacosPublisher(rules);
}
在這個例子中,接口 /hello
的限流會在 10 秒內逐步升到最大流量 20 QPS,防止系統受到突然的流量衝擊。
9. Sentinel 熔斷降級原理及實現方式
熔斷降級的概念就像電路中的 “保險絲”,當系統某個服務連續失敗時,Sentinel 會自動斷開該服務的調用,防止故障蔓延,確保系統的其他部分還能正常運作。
9.1 Sentinel 熔斷降級規則有哪些?
Sentinel 熔斷降級基於以下幾種規則:
-
慢調用比例熔斷:如果某個服務的調用時間持續超過設定的閾值(比如 500ms),並且慢調用的比例超過設定的閾值,Sentinel 會熔斷該服務。
-
異常比例熔斷:當某個服務的異常比例達到設定閾值(比如 50%),Sentinel 會觸發熔斷。
-
異常數熔斷:在一定時間窗口內,異常調用次數超過設定值,Sentinel 會觸發熔斷。
9.2 Sentinel 熔斷降級策略有哪些?
Sentinel 提供了三種熔斷策略:
-
快速失敗:當熔斷器被觸發時,所有請求直接失敗。
-
重試恢復:在熔斷一段時間後,Sentinel 會嘗試恢復調用,看服務是否恢復正常。
-
熔斷時間窗口:熔斷時間窗口結束後,Sentinel 會自動恢復服務的調用。
代碼示例:
@RestController
public class OrderController {
@GetMapping("/order")
@SentinelResource(value = "order", blockHandler = "orderFallback")
public String createOrder() {
// 模擬慢調用
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Order created";
}
// 熔斷後的降級處理
public String orderFallback(BlockException ex) {
return "Order service is temporarily unavailable, please try later.";
}
}
在這個例子中,如果 /order
接口調用時間持續超過設定的閾值,Sentinel 會觸發熔斷,直接返回降級響應。
10. Sentinel 與 Hystrix 對比
雖然 Sentinel 和 Hystrix 都是流量控制和降級保護的工具,但它們在架構設計和實現方式上有一些關鍵的區別:
- 功能覆蓋面:
-
Sentinel:提供了更全面的流量控制、熔斷降級功能,尤其在流量控制和多種限流策略上更靈活。
-
Hystrix:主要專注於熔斷、隔離和降級,功能相對聚焦。
- 擴展性:
-
Sentinel:由於 Sentinel 是阿里巴巴生態中的一部分,它對 Dubbo 和 Spring Cloud 生態支持更好,能夠通過動態規則調整更靈活地適應變化。
-
Hystrix:Hystrix 雖然功能強大,但社區逐漸轉向其他替代方案,維護力度有所減弱。
- 監控能力:
-
Sentinel:自帶控制檯界面,實時監控流量、調用情況,並且可以動態調整規則,使用上更方便。
-
Hystrix:也有監控界面,但功能相對較簡單,配置和擴展性不如 Sentinel 強大。
Sentinel 提供了豐富的流量控制和降級策略,尤其在面對複雜的分佈式系統時,能讓系統更加智能地進行動態
流量管理。對於現代的微服務架構,Sentinel 的靈活性和實時監控能力比 Hystrix 更具優勢。
總結
無論你使用哪種方案,在分佈式微服務架構中,降級保護機制都是不可或缺的關鍵設計。提前設計好降級策略,能讓你的系統在面對高併發或突發故障時從容應對,避免崩潰,並且有效保障用戶體驗。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/5uwloEIlo8NriFspqEJ5GA