規(guī)則與系統(tǒng)規(guī)則實(shí)戰(zhàn):白名單、黑名單與整機(jī)兜底)
Sentinel系列寫(xiě)到第五篇前幾篇我們把流控規(guī)則、降級(jí)規(guī)則、熱點(diǎn)規(guī)則都過(guò)了一遍到這篇剩下的就是授權(quán)規(guī)則和系統(tǒng)規(guī)則兩個(gè)模塊。標(biāo)題上雖然寫(xiě)了“簡(jiǎn)要說(shuō)明”但以我實(shí)際排查問(wèn)題的經(jīng)驗(yàn)來(lái)看這兩個(gè)模塊看著簡(jiǎn)單用起來(lái)翻車的概率比流控規(guī)則還高。很多人配了授權(quán)規(guī)則不生效配了系統(tǒng)規(guī)則發(fā)現(xiàn)接口全被攔了問(wèn)題往往出在沒(méi)搞懂這兩類規(guī)則在Sentinel整個(gè)攔截鏈里到底處于什么位置以及它們背后依賴了哪些前置條件。這篇就用實(shí)戰(zhàn)的方式把這兩塊拆開(kāi)講清楚適合已經(jīng)跑通Sentinel基礎(chǔ)流程、準(zhǔn)備在生產(chǎn)環(huán)境細(xì)化管控的同學(xué)參考。1. 授權(quán)規(guī)則與系統(tǒng)規(guī)則流控之外的“橫向兜底”從Sentinel的規(guī)則體系來(lái)看流控、降級(jí)、熱點(diǎn)規(guī)則針對(duì)的是單個(gè)資源解決的是“某個(gè)接口能不能扛住這個(gè)量”的問(wèn)題而授權(quán)規(guī)則和系統(tǒng)規(guī)則解決的是另一類問(wèn)題一個(gè)請(qǐng)求到底有沒(méi)有資格進(jìn)來(lái)以及這個(gè)應(yīng)用整體還能不能撐住。這兩類規(guī)則是橫向的作用在整個(gè)調(diào)用鏈上不單純掛在某一個(gè)資源名下。1.1 授權(quán)規(guī)則到底在管什么授權(quán)規(guī)則的核心是“我不能讓誰(shuí)進(jìn)來(lái)”區(qū)分白名單和黑名單兩種模式。舉個(gè)例子線上有個(gè)下單接口原本只應(yīng)該由訂單服務(wù)內(nèi)部調(diào)用結(jié)果被外部某個(gè)腳本盯上了每天定時(shí)刷你幾千次。流量不大觸發(fā)不了流控規(guī)則但接口邏輯確實(shí)在被白嫖業(yè)務(wù)上也說(shuō)不清這些請(qǐng)求到底是哪來(lái)的。這時(shí)候授權(quán)規(guī)則就能派上用場(chǎng)給請(qǐng)求來(lái)源打上標(biāo)記在Sentinel入口處直接拒絕黑名單來(lái)源或者反過(guò)來(lái)只允許白名單來(lái)源訪問(wèn)。它的設(shè)計(jì)思路是“來(lái)源識(shí)別 黑白名單判斷”所以有一個(gè)關(guān)鍵前提請(qǐng)求里必須能被解析出“來(lái)源應(yīng)用”。這個(gè)來(lái)源可以是一個(gè)Header、一個(gè)參數(shù)、甚至一段自定義邏輯。如果應(yīng)用里沒(méi)做來(lái)源解析授權(quán)規(guī)則就是一堆永遠(yuǎn)不生效的配置。1.2 系統(tǒng)規(guī)則是給“整機(jī)”設(shè)的保險(xiǎn)絲系統(tǒng)規(guī)則的價(jià)值不在于保護(hù)某個(gè)接口而在于保護(hù)整個(gè)應(yīng)用進(jìn)程。它的閾值維度包括系統(tǒng)Load、CPU使用率、入口QPS、平均RT、線程數(shù)五個(gè)維度任何一項(xiàng)超標(biāo)都會(huì)觸發(fā)全局?jǐn)r截。典型的場(chǎng)景是業(yè)務(wù)大促期間某個(gè)接口流量暴漲流控規(guī)則還沒(méi)來(lái)得及在對(duì)應(yīng)的資源上生效整個(gè)應(yīng)用就快被拖垮了。這時(shí)系統(tǒng)規(guī)則像保險(xiǎn)絲一樣先跳閘保住進(jìn)程不被打掛。這套機(jī)制的思路是“機(jī)器級(jí)別的兜底”不分接口、不分調(diào)用方一視同仁地限制入口流量。但它也有偏科的地方比如你設(shè)置了入口QPS為1000結(jié)果所有Web接口的請(qǐng)求都會(huì)算進(jìn)這1000如果某個(gè)接口本身會(huì)調(diào)用外部服務(wù)導(dǎo)致RT很高也可能把全局平均RT拉高觸發(fā)攔截。所以系統(tǒng)規(guī)則的閾值設(shè)置比流控規(guī)則更依賴對(duì)整機(jī)負(fù)載的理解不能拍腦袋填數(shù)字。2. 授權(quán)規(guī)則從配置到落地請(qǐng)求來(lái)源解析是關(guān)鍵授權(quán)規(guī)則看起來(lái)只有兩個(gè)選項(xiàng)白名單、黑名單再加一個(gè)來(lái)源應(yīng)用名稱。但實(shí)際上最容易出問(wèn)題的環(huán)節(jié)是“來(lái)源應(yīng)用名稱從哪來(lái)”。Sentinel不會(huì)自動(dòng)知道調(diào)用方是誰(shuí)它需要你告訴它一個(gè)來(lái)源標(biāo)識(shí)。2.1 授權(quán)規(guī)則的判定邏輯授權(quán)規(guī)則在Sentinel攔截鏈中位于統(tǒng)計(jì)完成之后、流控規(guī)則之前核心類是AuthoritySlot。當(dāng)一個(gè)請(qǐng)求進(jìn)入時(shí)Sentinel會(huì)調(diào)用RequestOriginParser解析出origin然后拿著這個(gè)origin和當(dāng)前資源的授權(quán)規(guī)則做匹配。白名單模式下limitApp里列出的來(lái)源允許通過(guò)未列出的來(lái)源直接拋AuthorityException黑名單模式正好反過(guò)來(lái)列出的來(lái)源被拒絕未列出的放行。這里有個(gè)容易被忽略的細(xì)節(jié)如果請(qǐng)求解析出來(lái)的origin為空或者為null在白名單模式下請(qǐng)求會(huì)直接拒絕。原因很簡(jiǎn)單白名單的語(yǔ)義是“只有列表里的才放行”一個(gè)連來(lái)源都標(biāo)識(shí)不出來(lái)的請(qǐng)求自然不在信任范圍內(nèi)。所以實(shí)現(xiàn)RequestOriginParser時(shí)至少要給一個(gè)兜底值比如default避免誤傷正常請(qǐng)求。2.2 來(lái)源解析RequestOriginParser的實(shí)現(xiàn)細(xì)節(jié)在Spring Boot的Web MVC場(chǎng)景下spring-cloud-starter-alibaba-sentinel自動(dòng)裝配了SentinelWebInterceptor它會(huì)從Spring容器中查找RequestOriginParser的實(shí)現(xiàn)類來(lái)解析來(lái)源。實(shí)現(xiàn)這個(gè)接口很簡(jiǎn)單Component public class HeaderRequestOriginParser implements RequestOriginParser { Override public String parseOrigin(HttpServletRequest request) { // 優(yōu)先取自定義Header很多內(nèi)部系統(tǒng)約定用X-Origin標(biāo)識(shí)調(diào)用來(lái)源 String origin request.getHeader(X-Origin); if (origin ! null origin.trim().length() 0) { return origin; } // 兜底返回一個(gè)固定值避免白名單模式下誤傷沒(méi)有來(lái)源標(biāo)識(shí)的請(qǐng)求 return default; } }這個(gè)類必須是Spring管理的Bean否則SentinelWebInterceptor拿不到它授權(quán)規(guī)則會(huì)靜默失效。還有一個(gè)容易踩的坑如果在項(xiàng)目里自定義了WebMvcConfigurer的addInterceptors方法要注意別覆蓋掉Sentinel的攔截器注冊(cè)否則整個(gè)Sentinel鏈路都不會(huì)生效。另外來(lái)源解析和資源名解析是兩回事。資源名解析走的是UrlCleaner用來(lái)把/order/create/123清洗成/order/create/*來(lái)源解析走的是RequestOriginParser只負(fù)責(zé)回答“這個(gè)請(qǐng)求是誰(shuí)發(fā)來(lái)的”。這兩個(gè)邏輯不要混在一起。2.3 控制臺(tái)配置步驟與白名單實(shí)戰(zhàn)假設(shè)現(xiàn)在有一個(gè)下單接口/order/create我們希望只允許來(lái)源為gateway的請(qǐng)求訪問(wèn)其他來(lái)源一律拒絕。操作很簡(jiǎn)單在控制臺(tái)左側(cè)菜單進(jìn)入“授權(quán)規(guī)則”點(diǎn)“新增授權(quán)規(guī)則”資源名填/order/create授權(quán)類型選“白名單”來(lái)源應(yīng)用填gateway保存后這條規(guī)則就生效了。規(guī)則底層邏輯等價(jià)于AuthorityRule rule new AuthorityRule(); rule.setResource(/order/create); rule.setLimitApp(gateway); rule.setStrategy(RuleConstant.AUTHORITY_WHITE); AuthorityRuleManager.loadRules(Collections.singletonList(rule));保存后可以啟動(dòng)一個(gè)請(qǐng)求不帶X-Origin頭去訪問(wèn)這個(gè)接口會(huì)看到類似SentinelBlockException: AuthorityException的異常帶上X-Origin: gateway就能正常通過(guò)。實(shí)踐中我建議同時(shí)配置一套黑名單規(guī)則來(lái)封殺惡意調(diào)用者比如來(lái)源標(biāo)識(shí)為spider的請(qǐng)求AuthorityRule blackRule new AuthorityRule(); blackRule.setResource(/order/create); blackRule.setLimitApp(spider); blackRule.setStrategy(RuleConstant.AUTHORITY_BLACK); AuthorityRuleManager.loadRules(Collections.singletonList(blackRule));這里有一個(gè)細(xì)節(jié)授權(quán)規(guī)則的資源名必須和Sentinel埋點(diǎn)的資源名完全一致。Spring MVC適配器默認(rèn)用請(qǐng)求URI作為資源名所以/order/create這個(gè)寫(xiě)法沒(méi)問(wèn)題如果項(xiàng)目里使用了自定義埋點(diǎn)SphU.entry(createOrder)那授權(quán)規(guī)則的資源名就要填createOrder而不是URL。3. 系統(tǒng)規(guī)則拆解五個(gè)維度的閾值怎么定、怎么生效系統(tǒng)規(guī)則在控制臺(tái)里看上去更簡(jiǎn)單一行配置五個(gè)可選項(xiàng)。但它的內(nèi)部機(jī)制比授權(quán)規(guī)則復(fù)雜不少因?yàn)樯婕皺C(jī)器級(jí)指標(biāo)的采集和入口流量的統(tǒng)計(jì)。3.1 五個(gè)維度背后的含義系統(tǒng)規(guī)則的五個(gè)維度分別是維度參數(shù)名含義典型設(shè)置參考LoadhighestSystemLoad系統(tǒng)當(dāng)前Load1分鐘平均僅Linux等類Unix系統(tǒng)有效核數(shù)的1.5倍到2倍比如4核機(jī)器設(shè)6.0CPUhighestCpuUsageCPU使用率0.0到1.0之間0.6到0.8留出緩沖RTavgRt所有入口流量的平均響應(yīng)時(shí)間單位毫秒業(yè)務(wù)P99耗時(shí)的1.5倍左右線程數(shù)maxThreads入口流量的并發(fā)線程數(shù)參考?jí)簻y(cè)得出的最大并發(fā)數(shù)入口QPSqps所有入口流量的總QPS峰值QPS的70%左右注意這里的RT和線程數(shù)都是“所有入口流量”的聚合指標(biāo)不是單個(gè)接口的指標(biāo)。設(shè)置RT300意味著所有Web請(qǐng)求的平均RT超過(guò)300ms就會(huì)觸發(fā)全局?jǐn)r截這在某些長(zhǎng)接口業(yè)務(wù)里會(huì)顯得很激進(jìn)。比如有一個(gè)接口本身要跑5秒但它的調(diào)用量很低平均RT只有200ms看起來(lái)不會(huì)觸發(fā)如果有一天這個(gè)慢接口調(diào)用量突然上來(lái)平均RT被拉高到300ms以上那所有接口都會(huì)被攔這其實(shí)是合理的——因?yàn)檎麢C(jī)已經(jīng)被慢調(diào)用拖住了。Load維度的判斷邏輯是只有當(dāng)系統(tǒng)Load超過(guò)閾值且當(dāng)前并發(fā)線程數(shù)超過(guò)系統(tǒng)容量時(shí)才會(huì)觸發(fā)單純Load高但線程數(shù)不高不觸發(fā)。這個(gè)設(shè)計(jì)是防止機(jī)器負(fù)載瞬間尖峰導(dǎo)致誤殺。在Windows上測(cè)試時(shí)Load指標(biāo)拿不到數(shù)據(jù)所以源碼里直接跳過(guò)這個(gè)維度的判斷也就是說(shuō)你在Windows上調(diào)Load規(guī)則它永遠(yuǎn)不會(huì)生效。3.2 入口流量的統(tǒng)計(jì)機(jī)制系統(tǒng)規(guī)則里反復(fù)提到“入口流量”這個(gè)詞很多人沒(méi)細(xì)想。Sentinel把流量分為IN和OUT兩種類型Web請(qǐng)求默認(rèn)是IN微服務(wù)內(nèi)部調(diào)用通常也是IN而OUT代表出口調(diào)用。系統(tǒng)規(guī)則只統(tǒng)計(jì)入口流量底層通過(guò)SystemMetricStatistics做滑動(dòng)窗口聚合默認(rèn)統(tǒng)計(jì)窗口是1秒每5秒檢查一次閾值。在默認(rèn)的Spring MVC適配器場(chǎng)景下所有被SentinelWebInterceptor攔截的請(qǐng)求都會(huì)自動(dòng)標(biāo)記為IN并累加到入口統(tǒng)計(jì)里。所以如果只配置了入口QPS500那應(yīng)用上所有Web請(qǐng)求的總QPS超過(guò)500就會(huì)全部被攔下來(lái)。這個(gè)行為對(duì)單體應(yīng)用來(lái)說(shuō)很直觀但在微服務(wù)架構(gòu)下要格外小心你開(kāi)了多個(gè)實(shí)例每個(gè)實(shí)例的入口QPS是獨(dú)立的控制臺(tái)上配置的500是單機(jī)值不是集群值。還有一個(gè)容易走彎路的地方系統(tǒng)規(guī)則在控制臺(tái)里只有“系統(tǒng)規(guī)則”一個(gè)入口配置的規(guī)則是掛在默認(rèn)入口資源Constants.ENTRY_RESOURCE上的。這個(gè)默認(rèn)入口資源可以理解為“應(yīng)用的總?cè)肟凇彼凶詣?dòng)埋點(diǎn)的請(qǐng)求都會(huì)歸到這里。但它也可以被替換Sentinel提供了一個(gè)擴(kuò)展點(diǎn)SystemRulesManager.registerSystemRulesProvider大部分場(chǎng)景用不到只需要知道有這么一個(gè)機(jī)制就好。3.3 擴(kuò)展入口規(guī)則與壓測(cè)驗(yàn)證我用一個(gè)實(shí)際案例來(lái)演示系統(tǒng)規(guī)則的完整落地過(guò)程。假設(shè)有一個(gè)4核8G的服務(wù)器預(yù)期峰值入口QPS在800左右線上要求P99 RT不高于300msCPU不能打滿。先通過(guò)一次簡(jiǎn)單的壓測(cè)拿到數(shù)據(jù)壓測(cè)工具設(shè)置200并發(fā)跑5分鐘得到平均RT180ms、入口QPS峰值1050、CPU最高81%。這些數(shù)據(jù)就是設(shè)置閾值的依據(jù)??刂婆_(tái)新增系統(tǒng)規(guī)則配置一組合理閾值SystemRule rule new SystemRule(); rule.setHighestSystemLoad(6.0); rule.setHighestCpuUsage(0.8); rule.setAvgRt(300); rule.setMaxThreads(200); rule.setQps(800); SystemRuleManager.loadRules(Collections.singletonList(rule));保存后再次壓測(cè)當(dāng)入口QPS超過(guò)800時(shí)新請(qǐng)求開(kāi)始被拒絕控制臺(tái)能看到SystemBlockException的攔截記錄CPU穩(wěn)定在80%以下服務(wù)不再響應(yīng)超時(shí)。這里要提醒一下系統(tǒng)規(guī)則的閾值不是越快越好。如果設(shè)置得過(guò)低比如CPU0.5業(yè)務(wù)上稍微有點(diǎn)波動(dòng)就觸發(fā)全局?jǐn)r截反而會(huì)影響正常流量。設(shè)置的原則是“在業(yè)務(wù)可接受的延遲范圍內(nèi)盡量多抗流量”具體數(shù)值要基于壓測(cè)數(shù)據(jù)迭代調(diào)整。關(guān)于代碼方式配置規(guī)則生產(chǎn)環(huán)境有爭(zhēng)議。用控制臺(tái)配置的好處是改動(dòng)即時(shí)生效、方便觀察用代碼配置的好處是隨應(yīng)用啟動(dòng)一起加載不依賴控制臺(tái)連接。我的建議是測(cè)試環(huán)境用控制臺(tái)快速調(diào)參確定閾值后固化到配置文件里用Sentinel的DataSource機(jī)制加載避免生產(chǎn)環(huán)境控制臺(tái)不穩(wěn)定導(dǎo)致規(guī)則丟失。4. 避坑指南這兩類規(guī)則最容易踩的坑這兩類規(guī)則看著簡(jiǎn)單實(shí)際用起來(lái)問(wèn)題不少。我整理了在多個(gè)項(xiàng)目里真實(shí)遇到的五類問(wèn)題基本可以覆蓋大部分排查場(chǎng)景。4.1 授權(quán)規(guī)則配了不生效這是排在第一的高頻問(wèn)題??刂婆_(tái)里規(guī)則明明保存了但請(qǐng)求進(jìn)不來(lái)也出不去心里沒(méi)底。查這個(gè)問(wèn)題的順序一般是第一確認(rèn)有沒(méi)有實(shí)現(xiàn)RequestOriginParser并且類上標(biāo)了Component。沒(méi)有實(shí)現(xiàn)請(qǐng)求來(lái)源解析控制臺(tái)填的來(lái)源應(yīng)用名稱就永遠(yuǎn)匹配不上白名單模式下所有請(qǐng)求都會(huì)被拒絕黑名單模式下規(guī)則形同虛設(shè)。第二確認(rèn)請(qǐng)求來(lái)源解析返回值和控制臺(tái)填寫(xiě)的值完全一致。解析邏輯里做了大小寫(xiě)轉(zhuǎn)換或去空格控制臺(tái)填的是Gateway解析返回的是gateway匹配不上。建議解析邏輯只做trim不做其他轉(zhuǎn)換避免自己給自己挖坑。第三確認(rèn)Sentinel鏈路真的生效了。檢查過(guò)濾器或攔截器有沒(méi)有被自定義配置覆蓋最直接的辦法是看請(qǐng)求日志里有沒(méi)有Sentinel相關(guān)輸出或者故意配一個(gè)流控規(guī)則驗(yàn)證一下基礎(chǔ)鏈路是否正常。4.2 系統(tǒng)規(guī)則在Windows上不生效很多人開(kāi)發(fā)機(jī)是Windows配了Load規(guī)則后發(fā)現(xiàn)壓測(cè)怎么都觸發(fā)不了不是規(guī)則寫(xiě)錯(cuò)了而是Windows沒(méi)有Load這個(gè)概念代碼里檢測(cè)到不支持就直接跳過(guò)了這個(gè)維度的判斷。如果要在開(kāi)發(fā)階段驗(yàn)證系統(tǒng)規(guī)則用CPU、RT、線程數(shù)、QPS這四個(gè)維度Load維度放到Linux測(cè)試環(huán)境再驗(yàn)。另外還要注意CPU使用率的獲取在不同JDK版本下表現(xiàn)有差異遇到CPU閾值始終不觸發(fā)的情況先看機(jī)器監(jiān)控里CPU是不是真的超過(guò)了閾值有時(shí)候虛擬機(jī)搶占導(dǎo)致監(jiān)控工具看到的CPU很高但Java層面拿到的數(shù)據(jù)有延遲。4.3 網(wǎng)關(guān)場(chǎng)景的來(lái)源解析是另一套APISpring Cloud Gateway場(chǎng)景下Sentinel的接入方式不是SentinelWebInterceptor而是SentinelGatewayFilter請(qǐng)求來(lái)源解析的注冊(cè)方式也完全不同。需要通過(guò)GatewayCallbackManager.setRequestOriginParser來(lái)注冊(cè)Configuration public class GatewayConfiguration { PostConstruct public void init() { GatewayCallbackManager.setRequestOriginParser(exchange - { String origin exchange.getRequest().getHeaders().getFirst(X-Origin); return origin ! null ? origin : default; }); } }很多人在網(wǎng)關(guān)場(chǎng)景下依然按Web MVC的方式寫(xiě)Component實(shí)現(xiàn)RequestOriginParser結(jié)果授權(quán)規(guī)則完全不生效就是因?yàn)檫@套適配器根本不會(huì)從Spring容器里去找那個(gè)接口。網(wǎng)關(guān)場(chǎng)景的資源名默認(rèn)是路由ID不是URL路徑配置授權(quán)規(guī)則時(shí)要用路由ID否則也匹配不上。4.4 閾值設(shè)置不能只靠感覺(jué)系統(tǒng)規(guī)則的五個(gè)維度不是所有都要配更建議只配置當(dāng)前需要的那一兩個(gè)維度避免相互干擾。比如只配入口QPS和CPU兩個(gè)維度其他維度保持未配置狀態(tài)Sentinel會(huì)跳過(guò)未配置的判斷。如果五個(gè)維度全部配滿可能出現(xiàn)某個(gè)維度先觸發(fā)導(dǎo)致其他規(guī)則來(lái)不及驗(yàn)證的情況給排查增加難度。閾值方面常見(jiàn)的錯(cuò)誤有兩種一種是把入口QPS設(shè)成單接口壓測(cè)的吞吐量但入口QPS是所有接口的總和二者差好幾倍另一種是把RT設(shè)成單個(gè)接口的P99但系統(tǒng)規(guī)則統(tǒng)計(jì)的是全局平均RT和單接口的延遲不是一個(gè)概念。這兩種錯(cuò)都會(huì)導(dǎo)致線上誤觸發(fā)壓測(cè)時(shí)需要特別區(qū)分。4.5 授權(quán)規(guī)則和系統(tǒng)規(guī)則的配合思路最后聊聊這兩類規(guī)則的配合。授權(quán)規(guī)則、系統(tǒng)規(guī)則、流控規(guī)則的觸發(fā)順序是授權(quán)規(guī)則最先判斷系統(tǒng)規(guī)則次之流控規(guī)則最后。也就是說(shuō)一個(gè)被授權(quán)規(guī)則拒絕的請(qǐng)求不會(huì)計(jì)入系統(tǒng)規(guī)則的入口統(tǒng)計(jì)也不會(huì)進(jìn)入流控判斷一個(gè)被系統(tǒng)規(guī)則攔截的請(qǐng)求不會(huì)再繼續(xù)往下走流控邏輯?;谶@個(gè)順序我通常會(huì)這樣設(shè)計(jì)最外層用授權(quán)規(guī)則擋住明確不允許的調(diào)用方這是第一道閘第二道用系統(tǒng)規(guī)則保護(hù)整機(jī)資源這是保命閘再往內(nèi)才是流控、降級(jí)、熱點(diǎn)這些精細(xì)化規(guī)則管控單個(gè)接口的流量形態(tài)。我在實(shí)際項(xiàng)目里第一次用系統(tǒng)規(guī)則時(shí)把入口QPS設(shè)置成了2000結(jié)果白天流量稍微一沖就直接全局?jǐn)r截業(yè)務(wù)方半夜打電話來(lái)找我。后來(lái)把閾值改到壓測(cè)峰值的50%再逐步上調(diào)用了一周才找到安全值。這個(gè)經(jīng)驗(yàn)是任何規(guī)則上線前都先在壓測(cè)環(huán)境壓一輪拿到真實(shí)數(shù)據(jù)再填閾值寧可先收緊再放寬也不要一開(kāi)始就給一個(gè)想當(dāng)然的大數(shù)字。生產(chǎn)環(huán)境里還有個(gè)小技巧系統(tǒng)規(guī)則觸發(fā)時(shí)會(huì)拒絕入口流量但返回給調(diào)用方的異常是BlockException如果你統(tǒng)一封裝了全局異常處理器記得把SystemBlockException也處理掉否則調(diào)用方拿到的可能是500而不是預(yù)期中的提示信息。授權(quán)規(guī)則拋出的AuthorityException同理也應(yīng)該在異常處理里做統(tǒng)一兜底給前端一個(gè)明確的提示而不是裸拋異常。這一篇把授權(quán)規(guī)則和系統(tǒng)規(guī)則講完Sentinel的規(guī)則體系就補(bǔ)得差不多了。下一篇準(zhǔn)備聊規(guī)則持久化和動(dòng)態(tài)數(shù)據(jù)源這應(yīng)該是生產(chǎn)環(huán)境里最后一塊拼圖了。