SpringCloud微服務(wù) Sentinel 實(shí)戰(zhàn)指南
Sentinel
Sentinel 是微服務(wù)里非常典型的一類(lèi)保護(hù)組件。它負(fù)責(zé)的是流量管控:當(dāng)流量突然變大、某個(gè)下游接口變慢、異常開(kāi)始擴(kuò)散時(shí),系統(tǒng)不要被一路拖垮。
如果說(shuō) Spring Cloud 核心概念解決的是“服務(wù)怎么拆、怎么找、怎么調(diào)”,那么 Sentinel 更像是在這些調(diào)用鏈外面再加一層保險(xiǎn)。微服務(wù)拆開(kāi)后,請(qǐng)求就不再只經(jīng)過(guò)一個(gè)系統(tǒng),而是會(huì)在網(wǎng)關(guān)、服務(wù) A、服務(wù) B、數(shù)據(jù)庫(kù)、緩存之間層層傳遞。任何一個(gè)點(diǎn)出問(wèn)題,都有可能變成整條鏈路的雪崩。
這也是為什么 Sentinel 的知識(shí)點(diǎn)看起來(lái)很多,既有流控規(guī)則,也有熱點(diǎn)參數(shù)限流、熔斷降級(jí)、授權(quán)規(guī)則、FallbackFactory、規(guī)則持久化。表面上它們是不同章節(jié),本質(zhì)上其實(shí)都在回答同一個(gè)問(wèn)題:系統(tǒng)變復(fù)雜之后,怎么把風(fēng)險(xiǎn)攔在局部,而不是讓故障擴(kuò)散到全局。
主線
- 先理解為什么微服務(wù)需要限流,以及流控規(guī)則怎么配。
- 再區(qū)分基于
QPS和基于并發(fā)線程數(shù)的兩種限流思路。 - 然后繼續(xù)往下看流控模式,直接、關(guān)聯(lián)、鏈路分別適合什么場(chǎng)景。
- 再往后是流控效果,
warm up和排隊(duì)等待本質(zhì)上是在控制“放行的節(jié)奏”。 - 當(dāng)普通流控還不夠精細(xì)時(shí),就需要熱點(diǎn)參數(shù)限流。
- 如果問(wèn)題已經(jīng)不是“流量太大”,而是“服務(wù)本身變慢、變脆”,就要進(jìn)入熔斷降級(jí)。
- 熔斷之后,調(diào)用方不能直接報(bào)錯(cuò)給用戶,所以又引出了
fallback、FallbackFactory和自定義異常返回結(jié)果。 - 最后,學(xué)習(xí)環(huán)境里可以靠 Dashboard 臨時(shí)配規(guī)則,但生產(chǎn)環(huán)境必須考慮規(guī)則持久化,也就是
pull/push模式。
為什么微服務(wù)需要 Sentinel
在微服務(wù)里,一個(gè)請(qǐng)求可能會(huì)先經(jīng)過(guò)網(wǎng)關(guān),再調(diào)用訂單服務(wù),訂單服務(wù)再調(diào)用戶服務(wù)、庫(kù)存服務(wù)、支付服務(wù)。只要中間有一個(gè)節(jié)點(diǎn)響應(yīng)慢了,上游線程就會(huì)被占??;如果大量線程一起等待,下游故障很快就會(huì)影響到上游。

- 如果是流量太大,就先做限流。
- 如果是某個(gè)依賴(lài)明顯不穩(wěn)定,就做熔斷降級(jí)。
- 如果不同來(lái)源的請(qǐng)求優(yōu)先級(jí)不同,就做授權(quán)控制。
- 如果請(qǐng)求被攔下來(lái)了,就返回一個(gè)可控、可讀的降級(jí)結(jié)果。
- 如果系統(tǒng)已經(jīng)準(zhǔn)備上線,就把這些規(guī)則從“內(nèi)存里的臨時(shí)配置”變成“可以持久化管理的正式規(guī)則”。
一、流量控制
1. 為什么先學(xué)流控
Sentinel 最核心的起點(diǎn)就是流量控制。因?yàn)楹芏嗑€上問(wèn)題,單位時(shí)間內(nèi)進(jìn)來(lái)的請(qǐng)求太多,或者請(qǐng)求處理得太慢,導(dǎo)致系統(tǒng)承受不住。
比如某個(gè)查詢(xún)接口平時(shí)每秒只有 20 個(gè)請(qǐng)求,數(shù)據(jù)庫(kù)完全頂?shù)米?。但活?dòng)一開(kāi)始,流量瞬間變成每秒 2000 個(gè)請(qǐng)求,這時(shí)數(shù)據(jù)庫(kù)、線程池、連接池都可能先后被打滿。流控做的事,就是在系統(tǒng)快到極限之前,主動(dòng)拒絕一部分請(qǐng)求,保持系統(tǒng)正常運(yùn)行。
基于流量控制的算法有木桶算法、漏斗算法和令牌算法。此處不過(guò)多展開(kāi)。
2. 基于 QPS 和基于并發(fā)線程數(shù)的流控
QPS 是每秒請(qǐng)求數(shù),限流策略是限制“請(qǐng)求進(jìn)入速度”。比如一個(gè)接口每秒最多只希望處理 100 次調(diào)用,那么就可以基于 QPS 配規(guī)則。
并發(fā)線程數(shù)的限流策略為關(guān)注同一時(shí)刻有多少請(qǐng)求正在處理中。它適合保護(hù)那些執(zhí)行時(shí)間較長(zhǎng)、線程占用明顯的接口。因?yàn)橛行┙涌陔m然每秒請(qǐng)求數(shù)不高,但每個(gè)請(qǐng)求都很慢,此時(shí)就要考慮線程占用限制與釋放的問(wèn)題。

3. 流控規(guī)則的核心字段
配置流控規(guī)則時(shí),不管是在代碼里還是在控制臺(tái)里配置,有幾個(gè)核心參數(shù)是必須了解的
resource,針對(duì)哪個(gè)資源生效,通常就是某個(gè)接口、某個(gè)方法、某個(gè)服務(wù)調(diào)用點(diǎn)。grade,按什么維度限流,是QPS還是并發(fā)線程數(shù)。count,規(guī)定了 QPS 的閾值。strategy,三種流控模式——直接、關(guān)聯(lián)、鏈路。controlBehavior,超過(guò)閾值之后怎么處理,是直接失敗、預(yù)熱還是排隊(duì)等待。
如果用代碼方式理解,一個(gè)最基礎(chǔ)的流控規(guī)則大概長(zhǎng)這樣:
FlowRule rule = new FlowRule();
rule.setResource("queryGoods"); # 規(guī)定資源
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); # 規(guī)定限流規(guī)則
rule.setCount(100); # QPS設(shè)置為100
FlowRuleManager.loadRules(List.of(rule)); 這段代碼規(guī)定資源名叫 queryGoods 的入口,QPS 超過(guò) 100 以后就開(kāi)始限流。
4. 三種流控模式,直接、關(guān)聯(lián)、鏈路
直接模式
直接模式最好理解,就是“誰(shuí)超了就限誰(shuí)”。比如 /goods/list 接口訪問(wèn)量過(guò)大,就直接對(duì) /goods/list 做限流。
這種模式適合最常見(jiàn)的單接口保護(hù)場(chǎng)景。
關(guān)聯(lián)模式
關(guān)聯(lián)模式的是限制與重要接口相關(guān)聯(lián)的資源
例如訂單創(chuàng)建接口和商品查詢(xún)接口都要訪問(wèn)數(shù)據(jù)庫(kù),秒殺時(shí)商品查詢(xún)量暴增,可能會(huì)把數(shù)據(jù)庫(kù)資源占滿,影響到下單。這時(shí)就可以設(shè)置,當(dāng)“商品查詢(xún)”資源壓力過(guò)大時(shí),限制“商品查詢(xún)”,把資源留給“下單”這種更重要的業(yè)務(wù)。
鏈路模式
鏈路模式關(guān)注的是,同一個(gè)資源可能從不同調(diào)用入口進(jìn)入,但這些入口的優(yōu)先級(jí)不一樣。
比如一個(gè) queryUser() 方法,既會(huì)被普通查詢(xún)頁(yè)面調(diào)用,也會(huì)被下單流程調(diào)用。雖然最終訪問(wèn)的是同一個(gè)方法,但“下單鏈路里的 queryUser()”和“普通查詢(xún)鏈路里的 queryUser()”業(yè)務(wù)價(jià)值不同。鏈路模式就能針對(duì)某一條調(diào)用路徑單獨(dú)限流。
這說(shuō)明 Sentinel 的資源觀念不只是“接口名”,而是“接口在整條調(diào)用鏈里扮演什么角色”。

5. 流控效果:快速失敗、warm up、排隊(duì)等待
閾值一旦超了,系統(tǒng)并不一定只有“直接拒絕”這一種做法。 warm up 和排隊(duì)等待,就是在討論“限流之后的處理節(jié)奏”。
快速失敗
快速失敗是最直接的方式。超過(guò)閾值后,后續(xù)請(qǐng)求立刻被拒絕。這種方式實(shí)現(xiàn)簡(jiǎn)單,保護(hù)性最強(qiáng),適合大多數(shù)接口。
warm up
warm up 適合服務(wù)冷啟動(dòng)的情況,如:資源正在初始化、數(shù)據(jù)庫(kù)連接也剛建立,假設(shè)這個(gè)服務(wù)的 QPS 為 100,剛啟動(dòng)時(shí)請(qǐng)求就達(dá)到閾值,此時(shí)服務(wù)器的資源還未完全初始化,也有可能服務(wù)器的崩潰。
所以 warm up 的思路不是一開(kāi)始就放開(kāi)全部流量,而是先給一個(gè)較低的通過(guò)閾值,然后隨著時(shí)間逐步升高,線性地升到設(shè)定的目標(biāo)閾值。
排隊(duì)等待
排隊(duì)等待適合對(duì)“勻速處理”有要求的場(chǎng)景。比如某些寫(xiě)庫(kù)操作,這時(shí)可以讓請(qǐng)求先處于隊(duì)列排隊(duì),按穩(wěn)定節(jié)奏通過(guò)。
6. 熱點(diǎn)參數(shù)限流
資源的接口的訪問(wèn)量是不一樣的,有些接口訪問(wèn)的頻繁,我們稱(chēng)之為熱點(diǎn)接口
例如商品詳情接口 /goods/{id} 平時(shí)很穩(wěn),但某個(gè)爆款商品 id=1001 突然被全網(wǎng)搶購(gòu)。這時(shí)接口本身不一定超限,真正熱點(diǎn)的是參數(shù) 1001。如果仍然按接口整體限流,就會(huì)誤傷所有其他商品請(qǐng)求。
熱點(diǎn)參數(shù)限流能做到:
- 同一個(gè)接口,不同參數(shù)值分開(kāi)統(tǒng)計(jì)。
- 對(duì)高頻熱點(diǎn)參數(shù)單獨(dú)限流。
- 必要時(shí)還能給某些特定參數(shù)配置例外閾值。
也就是說(shuō),普通流控解決的是“這個(gè)門(mén)太多人進(jìn)”,熱點(diǎn)參數(shù)限流解決的是“門(mén)本身沒(méi)問(wèn)題,但總有一小撮人瘋狂擠同一個(gè)窗口”。

7. 限流算法的理解重點(diǎn)
常見(jiàn)限流算法通常有下面幾類(lèi):
固定窗口 / 滑動(dòng)窗口


漏桶 / 令牌桶


二、熔斷降級(jí)
1. 熔斷的三種觸發(fā)條件
慢調(diào)用比例
當(dāng)一個(gè)資源的響應(yīng)時(shí)間持續(xù)很長(zhǎng),而且慢請(qǐng)求所占比例超過(guò)閾值時(shí),就可以觸發(fā)熔斷。
這個(gè)規(guī)則適合處理接口請(qǐng)求過(guò)慢的場(chǎng)景。
異常比例
如果在一個(gè)統(tǒng)計(jì)窗口內(nèi),請(qǐng)求中的異常占比明顯超過(guò)閾值,就說(shuō)明這個(gè)資源已經(jīng)處于高風(fēng)險(xiǎn)狀態(tài),可以暫時(shí)熔斷。
這個(gè)規(guī)則強(qiáng)調(diào)的是接口請(qǐng)求失敗的比例。
異常數(shù)
如果在統(tǒng)計(jì)窗口內(nèi),異常總數(shù)超過(guò)閾值時(shí)觸發(fā)熔斷。
2. 熔斷狀態(tài)機(jī)
狀態(tài)機(jī)用于監(jiān)控接口

CLOSED表示正常放行,請(qǐng)求可以正常通過(guò)。OPEN表示熔斷打開(kāi),這段時(shí)間內(nèi)請(qǐng)求不會(huì)繼續(xù)請(qǐng)求目標(biāo)資源,而是直接走降級(jí)邏輯,可能會(huì)請(qǐng)求到另外的備用接口。HALF_OPEN表示半開(kāi),也就是給系統(tǒng)一次“試著恢復(fù)”的機(jī)會(huì)。它不會(huì)一次性把流量全放開(kāi),而是先用少量探測(cè)請(qǐng)求看看下游是否真的恢復(fù)了。如果恢復(fù)了,就回到CLOSED;如果還是不行,就重新進(jìn)入OPEN。
三、授權(quán)規(guī)則與自定義異常返回
1. 授權(quán)規(guī)則
授權(quán)規(guī)則關(guān)注的是“誰(shuí)可以訪問(wèn)我”,對(duì)請(qǐng)求來(lái)源進(jìn)行白名單放行 / 黑名單攔截。
在微服務(wù)里,不同來(lái)源的請(qǐng)求優(yōu)先級(jí)可能不同。比如某個(gè)接口只允許內(nèi)部服務(wù)調(diào)用,不允許外部來(lái)源直接訪問(wèn);或者同一個(gè)資源,對(duì)某些來(lái)源放行,對(duì)另一些來(lái)源攔截。
Sentinel 的授權(quán)規(guī)則一般會(huì)基于 origin 來(lái)做判斷。你可以把 origin 理解成請(qǐng)求來(lái)源標(biāo)識(shí)。規(guī)則的本質(zhì)就是,對(duì)資源設(shè)置白名單或黑名單,讓不同來(lái)源得到不同處理。
2. 自定義異常返回結(jié)果
當(dāng)請(qǐng)求被 Sentinel 攔住時(shí),如果直接把原始異常棧丟給前端,用戶體驗(yàn)會(huì)很差,前端也很難統(tǒng)一處理。所以實(shí)際項(xiàng)目里,通常會(huì)把“被限流”“被降級(jí)”“被授權(quán)攔截”這些情況包裝成統(tǒng)一的業(yè)務(wù)返回。
在 Spring MVC 項(xiàng)目中,常見(jiàn)做法是實(shí)現(xiàn) BlockExceptionHandler:
@Component
public class CustomBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
String resourceName, BlockException e) throws Exception {
response.setStatus(429);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("code":429,"msg":"當(dāng)前請(qǐng)求被限流或降級(jí),請(qǐng)稍后再試");
}
}四、Fallback 行為與封裝接口 FallbackFactory
1. 為什么熔斷后還需要 fallback 行為
熔斷之后還需要降級(jí)邏輯,也就是 fallback。降級(jí)邏輯的目標(biāo)不是把功能完整替代掉,而是在主流程不可用時(shí),提供一個(gè)能接受的兜底結(jié)果。
2. FallbackFactory
Spring 為我們封裝了 FallbackFactory 接口,此實(shí)例將在出現(xiàn)任何類(lèi)型的錯(cuò)誤時(shí)被調(diào)用,任何關(guān)于 fallback 的錯(cuò)誤降級(jí)都可實(shí)現(xiàn)這個(gè)接口,捕獲異常。它可以拿到觸發(fā)降級(jí)的異常對(duì)象 Throwable,這樣在寫(xiě)兜底邏輯時(shí)就有更多上下文。
![[Pasted image 20260521163743.png|713]]
實(shí)現(xiàn)栗子??
@FeignClient(name = "user-service", fallbackFactory = UserClientFallbackFactory.class) # 需聲明fallbackFactory
public interface UserClient {
@GetMapping("/users/{id}")
String queryUserName(@PathVariable("id") Long id);
}
@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
return id -> "用戶服務(wù)暫時(shí)不可用,執(zhí)行了降級(jí)邏輯,原因:" + cause.getMessage();
}
}

五、規(guī)則管理與持久化
1. 規(guī)則配置
當(dāng)前的配置文件都是存放于內(nèi)存中的,重啟服務(wù)器后規(guī)則就沒(méi)了,且微服務(wù)中多臺(tái)示例部署,每個(gè)實(shí)例都規(guī)則可能都不同,管理配置會(huì)非常困難,我們需要平臺(tái)將規(guī)則配置統(tǒng)一管理起來(lái),方便修改同步。
2. pull / push 模式
pull 模式
應(yīng)用會(huì)主動(dòng)從某個(gè)外部規(guī)則源讀取配置,比如 Nacos、Apollo、ZooKeeper、文件或數(shù)據(jù)庫(kù)。應(yīng)用更像是規(guī)則的消費(fèi)者,規(guī)則中心保存正式配置,應(yīng)用自己去拉取。
push 模式
控制臺(tái)或配置中心把規(guī)則配置主動(dòng)推送到已經(jīng)注冊(cè)的實(shí)例中,實(shí)例(服務(wù)器)收到后會(huì)立刻更新
它的好處是實(shí)時(shí)性更好,規(guī)則修改后生效更快,也更接近真正的集中治理模式。生產(chǎn)環(huán)境里都會(huì)建議將 Sentinel 規(guī)則配置臺(tái)注冊(cè)到服務(wù)中心如 nacos 上,然后再由 nacos 推送,方便統(tǒng)一管理。

到此這篇關(guān)于SpringCloud微服務(wù) Sentinel 實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)SpringCloud微服務(wù) Sentinel 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一鍵部署SpringCloud 微服務(wù)的詳細(xì)流程
- SpringCloud集成sleuth和zipkin實(shí)現(xiàn)微服務(wù)鏈路追蹤的實(shí)戰(zhàn)分享
- SpringCloud微服務(wù)踩坑記錄分享
- SpringCloud中使用webclient(get和post)請(qǐng)求微服務(wù)接口數(shù)據(jù)
- SpringCloud微服務(wù)多應(yīng)用腳手架的搭建與部署方式
- docker部署SpringCloud微服務(wù)項(xiàng)目方式
- SpringCloudAlibaba微服務(wù)調(diào)用組件OpenFeign的方法
- SpringCloud整合OpenFeign實(shí)現(xiàn)微服務(wù)間的通信
- SpringCloud微服務(wù)集成Dubbo的詳細(xì)過(guò)程
- Sentinel網(wǎng)關(guān)限流與SpringCloud Gateway整合過(guò)程
相關(guān)文章
Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語(yǔ)句大全
MyBatis的動(dòng)態(tài)SQL是基于OGNL表達(dá)式的,它可以幫助我們方便的在SQL語(yǔ)句中實(shí)現(xiàn)某些邏輯,下面這篇文章主要給大家介紹了關(guān)于Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語(yǔ)句的相關(guān)資料,需要的朋友可以參考下2022-05-05
springboot如何使用logback-spring配置日志格式,并分環(huán)境配置
這篇文章主要介紹了springboot如何使用logback-spring配置日志格式,并分環(huán)境配置的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
關(guān)于Kill指令停掉Java程序的問(wèn)題
這篇文章主要介紹了Kill指令停掉Java程序的思考,主要探究kill指令和java的關(guān)閉鉤子的問(wèn)題,需要的朋友可以參考下2021-10-10
Java中實(shí)現(xiàn)文件預(yù)覽的功能(實(shí)例代碼)
大家都知道word,Excel,PPT實(shí)現(xiàn)在線預(yù)覽常用的方式就是先轉(zhuǎn)換成pdf,然后在進(jìn)行預(yù)覽,下面給大家介紹Java中如何實(shí)現(xiàn)文件預(yù)覽的功能,需要的朋友可以參考下2023-05-05
Java實(shí)現(xiàn)將導(dǎo)出帶格式的Excel數(shù)據(jù)到Word表格
在Word中制作報(bào)表時(shí),我們經(jīng)常需要將Excel中的數(shù)據(jù)復(fù)制粘貼到Word中,這樣則可以直接在Word文檔中查看數(shù)據(jù)而無(wú)需打開(kāi)另一個(gè)Excel文件。本文將通過(guò)Java應(yīng)用程序詳細(xì)介紹如何把帶格式的Excel數(shù)據(jù)導(dǎo)入Word表格。希望這篇文章能對(duì)大家有所幫助2022-11-11

