目錄
- 第一章 Sentinel的介紹
- 1.1、Sentinel是什么
- 1.2、Sentinel的特性
- 1.3、Sentinel的對比
- 第二章 Sentinel的安裝與運行
- 2.1、下載Sentinel
- 2.2、運行Sentinel
- 2.3、訪問Sentinel
- 第三章 Sentinel的整合與演示
- 3.1、專案的準備與啟動
- 3.2、商品服務整合哨兵
- 3.2.1、新增依賴
- 3.2.2、新增配置
- 3.2.3、實時監控
- 3.2.4、簇點鏈路
- 第四章 Sentinel的流控規則
- 4.1、規則介紹
- 4.2、規則演示
- 4.2.1、流控模式:直接
- 4.2.2、流控模式:關聯
- 4.2.3、流控模式:鏈路
- 4.2.4、流控效果:快速失敗
- 4.2.5、流控效果:Warm Up
- 4.2.6、流控效果:排隊等待
- 第五章 Sentinel的降級規則
- 5.1、規則介紹
- 5.2、規則演示
- 5.2.1、熔斷策略:慢呼叫比例
- 5.2.2、熔斷策略:例外比例
- 5.2.3、熔斷策略:例外數
- 第六章 Sentinel的熱點規則
- 6.1、規則介紹
- 6.2、規則演示
- 6.2.1、熱點引數限流
- 6.2.2、引數例外項
- 第七章 Sentinel的授權規則
- 7.1、規則介紹
- 7.2、規則演示
- 7.2.1、白名單測驗
- 7.2.2、黑名單測驗
- 第八章 Sentinel的系統規則
- 8.1、規則介紹
- 8.2、規則演示
- 第九章 Sentinel的保護模式
- 9.1、默認地址埋點保護
- 9.2、手寫代碼埋點保護
- 9.3、使用注解埋點保護
- 第十章 Sentinel與遠程呼叫
- 10.1、RestTemplate整合Sentinel
- 10.1.1、開啟Sentinel配置
- 10.1.2、整合Sentinel注解
- 10.1.3、修改商品服務
- 10.1.4、修改訂單服務
- 10.1.5、訪問測驗地址
- 10.1.6、添加流控規則
- 10.1.7、添加降級規則
- 10.1.8、測驗最終效果
- 10.2、OpenFeign整合Sentinel
- 10.2.1、匯入相關依賴
- 10.2.2、開啟相關配置
- 10.2.3、配置主啟動類
- 10.2.4、撰寫業務介面
- 10.2.5、撰寫控制器類
- 10.2.6、訪問測驗地址
- 10.2.7、添加流控規則
- 10.2.8、測驗流控規則
- 第十一章 Sentinel資料持久化
- 11.1、原始模式
- 11.2、Pull模式
- 11.2.1、撰寫代碼
- 11.2.2、配置代碼
- 11.2.3、重啟工程
- 11.2.4、添加流控規則
- 11.2.5、添加降級規則
- 11.2.6、添加熱點規則
- 11.2.7、添加授權規則
- 11.2.8、添加系統規則
- 11.2.9、重啟以后查看
- 11.3、Push模式
- 11.3.1、匯入依賴
- 11.3.2、撰寫配置
- 11.3.3、創建檔案
- 11.3.4、重啟應用
- 第十二章 Sentinel的其他流控
- 12.1、集群流控
- 12.2、網關流控
配套資料,免費下載
鏈接:https://pan.baidu.com/s/1-eRFozbFIShqbqNRFD9KDw
提取碼:rt3w
復制這段內容后打開百度網盤手機App,操作更方便哦
第一章 Sentinel的介紹
1.1、Sentinel是什么
隨著微服務的流行,服務和服務之間的穩定性變得越來越重要,提起 Spring Cloud 的限流降級組件,一般首先想到的是 Netflix 的 Hystrix,

不過就在2018年底,Netflix 宣布不再積極開發 Hystrix,該專案將處于維護模式,官方表示 1.5.18 版本的 Hystrix 已經足夠穩定,可以滿足 Netflix 現有應用的需求,所以接下來其會把焦點轉向對于自適應的實作,更多關注對應用程式的實時性能做出回應,對于新應用的熔斷需求,將采用其它專案實作,Netflix 推薦了 Resilience4j,
作為 Spring Cloud Netflix 重要套件,Hystrix已經成為保障微服務穩定性的首選應用,其實除了 Netflix 和 Resilience4j,限流降級還有一個新的選擇,就是阿里巴巴的 Sentinel 組件,

Sentinel 是面向分布式服務架構的流量控制組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個維度來幫助開發者保障微服務的穩定性,
- 2012 年,Sentinel 誕生,主要功能為入口流量控制,
- 2013-2017 年,Sentinel 在阿里巴巴集團內部迅速發展,成為基礎技術模塊,覆寫了所有的核心場景,Sentinel 也因此積累了大量的流量歸整場景以及生產實踐,
- 2018 年,Sentinel 開源,并持續演進,
- 2019 年,Sentinel 朝著多語言擴展的方向不斷探索,推出 C++ 原生版本,同時針對 Service Mesh 場景也推出了 Envoy 集群流量控制支持,以解決 Service Mesh 架構下多語言限流的問題,
- 2020 年,推出 Sentinel Go 版本,繼續朝著云原生方向演進,
Sentinel 在經過阿里巴巴內部一系列秒殺大促,特別是雙11這樣電商大促中的錘煉,目前已有不少企業在使用開源版本和云版本的 Sentinel,包括順豐、VIVO、每日優鮮、拼多多、易企秀、愛奇藝、融金所、VIPKID、喜馬拉雅FM、百融金服等,
官方檔案:https://github.com/alibaba/Sentinel/wiki
原始碼地址:https://github.com/alibaba/Sentinel
1.2、Sentinel的特性
Sentinel 有以下特征:
- 豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的范圍)、訊息削峰填谷、集群流量控制、實時熔斷下游不可用應用等,
- 完備的實時監控:Sentinel 同時提供實時的監控功能,您可以在控制臺中看到接入應用的單臺機器秒級資料,甚至 500 臺以下規模的集群的匯總運行情況,
- 廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合,您只需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel,
- 完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展介面,您可以通過實作擴展介面來快速地定制邏輯,例如定制規則管理、適配動態資料源等,
Sentinel 的主要特性:

Sentinel 的開源生態:

Sentinel 的組成部分:
- 核心庫(Java 客戶端)不依賴任何框架/庫,能夠運行于所有 Java 運行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持,
- 控制臺(Dashboard)基于 Spring Boot 開發,打包后可以直接運行,不需要額外的 Tomcat 等應用容器,
1.3、Sentinel的對比
| Sentinel | Hystrix | resilience4j | |
|---|---|---|---|
| 隔離策略 | 信號量隔離(并發控制) | 執行緒池隔離/信號量隔離 | 信號量隔離 |
| 熔斷降級策略 | 基于慢呼叫比例、例外比例、例外數 | 基于例外比例 | 基于例外比例、回應時間 |
| 實時統計實作 | 滑動視窗(LeapArray) | 滑動視窗(基于 RxJava) | Ring Bit Buffer |
| 動態規則配置 | 支持近十種動態資料源 | 支持多種資料源 | 有限支持 |
| 擴展性 | 多個擴展點 | 插件的形式 | 介面的形式 |
| 基于注解的支持 | 支持 | 支持 | 支持 |
| 單機限流 | 基于 QPS,支持基于呼叫關系的限流 | 有限的支持 | Rate Limiter |
| 集群流控 | 支持 | 不支持 | 不支持 |
| 流量整形 | 支持預熱模式與勻速排隊控制效果 | 不支持 | 簡單的 Rate Limiter 模式 |
| 系統自適應保護 | 支持 | 不支持 | 不支持 |
| 熱點識別/防護 | 支持 | 不支持 | 不支持 |
| 多語言支持 | Java/Go/C++ | Java | Java |
| Service Mesh 支持 | 支持 Envoy/Istio | 不支持 | 不支持 |
| 控制臺 | 提供開箱即用的控制臺,可配置規則、實時監控、機器發現等 | 簡單的監控查看 | 不提供控制臺,可對接其它監控系統 |
第二章 Sentinel的安裝與運行
2.1、下載Sentinel
下載地址:https://github.com/alibaba/Sentinel/releases/download/1.8.1/sentinel-dashboard-1.8.1.jar
2.2、運行Sentinel
運行命令:java -jar sentinel-dashboard-1.8.1.jar
2.3、訪問Sentinel
訪問地址:http://localhost:8080/,登錄賬戶:sentinel,登錄密碼:sentinel


第三章 Sentinel的整合與演示
3.1、專案的準備與啟動
(1)以單機模式啟動nacos:startup.cmd -m standalone
(2)使用idea匯入02-服務注冊與配置:Nacos中的spring-cloud-alibaba-study

3.2、商品服務整合哨兵
3.2.1、新增依賴
在service-goods的pom.xml中新增如下依賴:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
3.2.2、新增配置
在service-goods的application.yaml中新增如下配置:
spring:
cloud:
sentinel:
transport:
dashboard: http://localhost:8080
在service-goods的bootstrap.yaml中注釋如下配置:
spring:
application:
name: service-goods
profiles:
active: dev #激活開發環境配置
cloud:
nacos:
discovery:
server-addr: http://localhost:8848
# config:
# server-addr: http://localhost:8848
# prefix: application #指定組態檔的前綴
# file-extension: yaml #指定組態檔的拓展名
# group: DEFAULT_GROUP #指定組態檔所在組
# namespace: public #指定組態檔所在命名空間
在service-goods中洗掉ReadConfigController控制類
3.2.3、實時監控
啟動ServiceGoodsApplication7001,然后訪問地址:http://localhost:7001/goods/findByGid?gid=1,然后查看Sentinel控制臺:

3.2.4、簇點鏈路
簇點鏈路:
在這個功能模塊下,你可以清晰地看出當前資源的訪問情況,并且可以為資源添加流控、降級、熱點、授權等規則,這些規則會在后邊詳細介紹,
樹狀視圖:

串列視圖:

相關概念:
每秒查詢率(QPS) :每秒查詢率QPS是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準,在因特網上,作為域名系統服務器的機器的性能經常用每秒查詢率來衡量,對應fetches/sec,即每秒的回應請求數,也即是最大吞吐能力,
回應時間(RT) :回應時間是指系統對請求作出回應的時間,直觀上看,這個指標與人對軟體性能的主觀感受是非常一致的,因為它完整地記錄了整個計算機系統處理請求的時間,由于一個系統通常會提供許多功能,而不同功能的處理邏輯也千差萬別,因而不同功能的回應時間也不盡相同,甚至同一功能在不同輸入資料的情況下回應時間也不相同,所以,在討論一個系統的回應時間時,人們通常是指該系統所有功能的平均時間或者所有功能的最大回應時間,當然,往往也需要對每個或每組功能討論其平均回應時間和最大回應時間,對于單機的沒有并發操作的應用系統而言,人們普遍認為回應時間是一個合理且準確的性能指標,需要指出的是,回應時間的絕對值并不能直接反映軟體的性能的高低,軟體性能的高低實際上取決于用戶對該回應時間的接受程度,對于一個游戲軟體來說,回應時間小于100毫秒應該是不錯的,回應時間在1秒左右可能屬于勉強可以接受,如果回應時間達到3秒就完全難以接受了,而對于編譯系統來說,完整編譯一個較大規模軟體的源代碼可能需要幾十分鐘甚至更長時間,但這些回應時間對于用戶來說都是可以接受的,
第四章 Sentinel的流控規則
4.1、規則介紹
官方說明:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

- 資源名:一般是我們的請求路徑
- 針對來源:是指來自于哪個應用
- 閾值型別:分為QPS或執行緒數
- 單機閾值:單個節點的QPS或執行緒數閾值
- 是否集群:被請求的服務是否集群部署
- 流控模式:
- 直接,就是直接對該資源進行控制
- 關聯,關聯某一個資源(/app2),被關聯的資源/app2達到閾值2,則限制當前資源/test的訪問
- 鏈路,記錄指定鏈路上的流量
- 流控效果:(執行緒數閾值型別不存在此屬性)
- 快速失敗 ,直接限制
- Warm Up,根據coldFactor(默認為3)的值,從 閾值/coldFactor,經過預熱的時長,才達到設定的QPS閾值,比如設定QPS閾值為100,那么100/3 =33,用33作為最初的閾值,然后在10秒到達100后再開始限流,這個coldFactor值,可以在組態檔中配置
- 排隊等待,在QPS閾值到達后,新的請求就等待,直到超時,可以適用于突發流量的請求
4.2、規則演示
4.2.1、流控模式:直接
(1)在GoodsController中,添加測驗方法,然后重啟,代碼如下:
@RequestMapping("/goods/testA")
public String testA() {
return "server port:" + port + ",testA...";
}
(2)訪問測驗方法,訪問地址:http://localhost:7001/goods/testA

(3)添加流控規則,如下圖:

(4)訪問測驗方法,快速連續訪問多次:http://localhost:7001/goods/testA

按照我們的配置,1秒鐘以內只能有1個請求(單機閾值)通過,如果你在1秒以內快速連續訪問,就會觸發流量限制,
4.2.2、流控模式:關聯
(1)在GoodsController中,添加測驗方法,然后重啟,代碼如下:
@RequestMapping("/goods/testB")
public String testB() {
return "server port:" + port + ",testB...";
}
(2)訪問測驗方法,訪問地址:http://localhost:7001/goods/testA

(3)訪問測驗方法,訪問地址:http://localhost:7001/goods/testB

(4)添加流控規則,如下圖:

(5)訪問測驗方法,并發訪問:http://localhost:7001/goods/testB,這里可以采用JMeter或者Postman,然后訪問:http://localhost:7001/goods/testA

簡單的來說:關聯的/goods/testB資源一旦限流,當前資源/goods/testA也會被限流保護起來,但是測驗的時候并不好測,需要掌握并發測驗知識,
4.2.3、流控模式:鏈路
(1)添加流控規則,如下圖:

(2)訪問測驗方法,快速連續訪問多次:http://localhost:7001/goods/testB

NodeSelectorSlot 中記錄了資源之間的呼叫鏈路,這些資源通過呼叫關系,相互之間構成一棵呼叫樹,這棵樹的根節點是一個名字為 machine-root 的虛擬節點,呼叫鏈的入口都是這個虛節點的子節點,
一棵典型的呼叫樹如下圖所示:
machine-root
/ \
/ \
Entrance1 Entrance2
/ \
/ \
DefaultNode(nodeA) DefaultNode(nodeA)
上圖中來自入口 Entrance1 和 Entrance2 的請求都呼叫到了資源 NodeA,Sentinel 允許只根據某個入口的統計資訊對資源限流,比如我們可以設定 strategy 為 RuleConstant.STRATEGY_CHAIN,同時設定 refResource 為 Entrance1 來表示只有從入口 Entrance1 的呼叫才會記錄到 NodeA 的限流統計當中,而不關心經 Entrance2 到來的呼叫,
同理,我們現在對/goods/testB的限流都是經過sentinel_spring_web_context這個虛擬節點的,如下圖:

4.2.4、流控效果:快速失敗
快速失敗(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默認的流量控制方式,當QPS超過任意規則的閾值后,新的請求就會被立即拒絕,拒絕方式為拋出FlowException,這種方式適用于對系統處理能力確切已知的情況下,比如通過壓測確定了系統的準確水位時,我們之前所有的測驗的流控效果都是快速失敗,當失敗會顯示如下資訊:

4.2.5、流控效果:Warm Up
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即預熱/冷啟動方式,當系統長期處于低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮,通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮,
當流量突然增大的時候,我們常常會希望系統從空閑狀態到繁忙狀態的切換的時間長一些,即如果系統在此之前長期處于空閑的狀態,我們希望處理請求的數量是緩步的增多,經過預期的時間以后,到達系統處理請求個數的最大值,Warm Up(冷啟動,預熱)模式就是為了實作這個目的的,
通常冷啟動的程序系統允許通過的 QPS 曲線如下圖所示:

4.2.6、流控效果:排隊等待
排隊等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶演算法,
它的中心思想是,以固定的間隔時間讓請求通過,當請求到來的時候,如果當前請求距離上個通過的請求通過的時間間隔不小于預設值,則讓當前請求通過;否則,計算當前請求的預期通過時間,如果該請求的預期通過時間小于規則預設的 timeout 時間,則該請求會等待直到預設時間到來通過(排隊等待處理);若預期的通過時間超出最大排隊時長,則直接拒接這個請求,
這種方式適合用于請求以突刺狀來到,這個時候我們不希望一下子把所有的請求都通過,這樣可能會把系統壓垮;同時我們也期待系統以穩定的速度,逐步處理這些請求,以起到“削峰填谷”的效果,而不是拒絕所有請求,
例如,如果系統使用 Apache RocketMQ 來收發訊息,系統在某個時間突然收到大量訊息,我們希望以固定的速率來處理訊息,而不是一下子拒絕這些訊息,這個時候可以使用勻速器,也就是給訊息排隊,效果如下所示:

注意:勻速排隊模式暫時不支持 QPS > 1000 的場景,
第五章 Sentinel的降級規則
5.1、規則介紹
官方說明:https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
除了流量控制以外,對呼叫鏈路中不穩定的資源進行熔斷降級也是保障高可用的重要措施之一,一個服務常常會呼叫別的模塊,可能是另外的一個遠程服務、資料庫,或者第三方 API 等,例如,支付的時候,可能需要遠程呼叫銀聯提供的 API;查詢某個商品的價格,可能需要進行資料庫查詢,然而,這個被依賴服務的穩定性是不能保證的,如果依賴的服務出現了不穩定的情況,請求的回應時間變長,那么呼叫服務的方法的回應時間也會變長,執行緒會產生堆積,最終可能耗盡業務自身的執行緒池,服務本身也變得不可用,

現代微服務架構都是分布式的,由非常多的服務組成,不同服務之間相互呼叫,組成復雜的呼叫鏈路,以上的問題在鏈路呼叫中會產生放大的效果,復雜鏈路上的某一環不穩定,就可能會層層級聯,最終導致整個鏈路都不可用,因此我們需要對不穩定的弱依賴服務呼叫進行熔斷降級,暫時切斷不穩定呼叫,避免區域不穩定因素導致整體的雪崩,熔斷降級作為保護自身的手段,通常在客戶端(呼叫端)進行配置,

Sentinel 提供以下幾種熔斷策略:
- 慢呼叫比例 (
SLOW_REQUEST_RATIO):選擇以慢呼叫比例作為閾值,需要設定允許的慢呼叫 RT(即最大的回應時間),請求的回應時間大于該值則統計為慢呼叫,當單位統計時長(statIntervalMs)內請求數目大于設定的最小請求數目,并且慢呼叫的比例大于閾值,則接下來的熔斷時長內請求會自動被熔斷,經過熔斷時長后熔斷器會進入探測恢復狀態(HALF-OPEN 狀態),若接下來的一個請求回應時間小于設定的慢呼叫 RT 則結束熔斷,若大于設定的慢呼叫 RT 則會再次被熔斷, - 例外比例 (
ERROR_RATIO):當單位統計時長(statIntervalMs)內請求數目大于設定的最小請求數目,并且例外的比例大于閾值,則接下來的熔斷時長內請求會自動被熔斷,經過熔斷時長后熔斷器會進入探測恢復狀態(HALF-OPEN 狀態),若接下來的一個請求成功完成(沒有錯誤)則結束熔斷,否則會再次被熔斷,例外比率的閾值范圍是[0.0, 1.0],代表 0% - 100%, - 例外數 (
ERROR_COUNT):當單位統計時長內的例外數目超過閾值之后會自動進行熔斷,經過熔斷時長后熔斷器會進入探測恢復狀態(HALF-OPEN 狀態),若接下來的一個請求成功完成(沒有錯誤)則結束熔斷,否則會再次被熔斷,
最小請求數:觸發熔斷的最小請求數目,若當前統計視窗內的請求數小于此值,即使達到熔斷條件規則也不會觸發,
注意:例外降級僅針對業務例外,對 Sentinel 限流降級本身的例外(BlockException)不生效,為了統計例外比例或例外數,需要通過 Tracer.trace(ex) 記錄業務例外,開源整合模塊,如 Sentinel Dubbo Adapter, Sentinel Web Servlet Filter 或 @SentinelResource 注解會自動統計業務例外,無需手動呼叫,
5.2、規則演示
5.2.1、熔斷策略:慢呼叫比例
(1)修改service-goods的GoodsController的findByGid方法,然后重啟,代碼如下:
@RequestMapping("/goods/findByGid")
public String findByGid(@RequestParam("gid") String gid) {
//模擬業務超時
if ("0".equals(gid)) {
try { Thread.sleep(500); } catch (Exception e) {}
}
//模擬業務正常
if ("1".equals(gid)) {
return "server port:" + port + ",findByGid:" + gid;
}
//模擬業務出錯
if ("2".equals(gid)) {
int i = 1 / 0;
}
return "other ...";
}
(2)訪問測驗方法,訪問地址:http://localhost:7001/goods/findByGid?gid=1
(3)添加降級規則,如下圖:

(4)訪問超時方法,連續多次訪問地址:http://localhost:7001/goods/findByGid?gid=0

(5)如果此時訪問正常的方法,訪問地址:http://localhost:7001/goods/findByGid?gid=1

(6)過一會,再次訪問正常的業務地址,發現服務又恢復了
5.2.2、熔斷策略:例外比例
(1)修改降級規則,如下圖:

(2)訪問出錯地址,連續多次訪問地址:http://localhost:7001/goods/findByGid?gid=2

(3)如果此時訪問正常的方法,訪問地址:http://localhost:7001/goods/findByGid?gid=1

(4)過一會,再次訪問正常的業務地址,發現服務又恢復了
5.2.3、熔斷策略:例外數
(1)修改降級規則,如下圖:

(2)訪問出錯地址,連續多次訪問地址:http://localhost:7001/goods/findByGid?gid=2

(3)如果此時訪問正常的方法,訪問地址:http://localhost:7001/goods/findByGid?gid=1

(4)過一會,再次訪問正常的業務地址,發現服務又恢復了
第六章 Sentinel的熱點規則
6.1、規則介紹
官方說明:https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
何為熱點?熱點即經常訪問的資料,很多時候我們希望統計某個熱點資料中訪問頻次最高的 Top K 資料,并對其訪問進行限制,比如:
- 商品 ID 為引數,統計一段時間內最常購買的商品 ID 并進行限制
- 用戶 ID 為引數,針對一段時間內頻繁訪問的用戶 ID 進行限制
熱點引數限流會統計傳入引數中的熱點引數,并根據配置的限流閾值與模式,對包含熱點引數的資源呼叫進行限流,熱點引數限流可以看做是一種特殊的流量控制,僅對包含熱點引數的資源呼叫生效,
Sentinel 利用 LRU 策略統計最近最常訪問的熱點引數,結合令牌桶演算法來進行引數級別的流控,熱點引數限流支持集群模式,

注意:熱點規則需要使用@SentinelResource(“app”)注解,否則不生效,并且引數必須是7種基本資料型別才會生效,
6.2、規則演示
6.2.1、熱點引數限流
(1)修改service-goods的GoodsController的findByGid方法,然后重啟,代碼如下:
@RequestMapping("/goods/findByGid")
@SentinelResource(value = "findByGidHotKey", blockHandler = "findByGidBlockHandler")
public String findByGid(@RequestParam("gid") String gid) {
//模擬業務超時
if ("0".equals(gid)) {
try { Thread.sleep(500); } catch (Exception e) {}
}
//模擬業務正常
if ("1".equals(gid)) {
return "server port:" + port + ",findByGid:" + gid;
}
//模擬業務出錯
if ("2".equals(gid)) {
int i = 1 / 0;
}
return "other ...";
}
//兜底方法
public String findByGidBlockHandler(String gid, BlockException exception) {
return "限流了...";
}
(2)訪問測驗方法,訪問地址:http://localhost:7001/goods/findByGid?gid=1
(3)添加熱點規則,如下圖:

(4)訪問測驗地址,連續快速訪問:http://localhost:7001/goods/findByGid?gid=1

6.2.2、引數例外項
(1)修改熱點規則,如下圖:

(2)訪問測驗地址,連續快速訪問,發現并不會限流:http://localhost:7001/goods/findByGid?gid=10086

第七章 Sentinel的授權規則
7.1、規則介紹
官方說明:https://github.com/alibaba/Sentinel/wiki/%E9%BB%91%E7%99%BD%E5%90%8D%E5%8D%95%E6%8E%A7%E5%88%B6
很多時候,我們需要根據呼叫來源來判斷該次請求是否允許放行,這時候可以使用 Sentinel 的來源訪問控制(黑白名單控制)的功能,來源訪問控制根據資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位于白名單內時才可通過;若配置黑名單則請求來源位于黑名單時不通過,其余的請求通過,

7.2、規則演示
7.2.1、白名單測驗
(1)在service-goods下,添加來源決議器,類名稱com.caochenlei.config.MyRequestOriginParser
@Component
public class MyRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
String origin = request.getParameter("origin");
return origin;
}
}
(2)重啟服務,然后訪問地址:http://localhost:7001/goods/findByGid?gid=1
(3)添加授權規則,如下圖:

(4)訪問測驗地址,我們攜帶上允許的來源,訪問地址:http://localhost:7001/goods/findByGid?gid=1&origin=myapp

(5)如果我們換一個來源,則限流,訪問地址:http://localhost:7001/goods/findByGid?gid=1&origin=aaa

7.2.2、黑名單測驗
(1)修改授權規則,如下圖:

(2)如果此時是myapp的來源進行訪問,會被限流,訪問地址:http://localhost:7001/goods/findByGid?gid=1&origin=myapp

(3)如果我們不攜帶或者攜帶不是黑名單的來源,則不會限流,訪問地址:http://localhost:7001/goods/findByGid?gid=1&origin=aaa

第八章 Sentinel的系統規則
8.1、規則介紹
官方介紹:https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81
Sentinel 系統自適應限流從整體維度對應用入口流量進行控制,結合應用的 Load、總體平均 RT、并發執行緒數、入口 QPS 、CPU 使用率等幾個維度的監控指標,通過自適應的流控策略,讓系統的入口流量和系統的負載達到一個平衡,讓系統盡可能跑在最大吞吐量的同時保證系統整體的穩定性,

系統規則支持以下的模式:
- Load 自適應(僅對 Linux/Unix-like 機器生效):系統的 load1 作為啟發指標,進行自適應系統保護,當系統 load1 超過設定的啟發值,且系統當前的并發執行緒數超過估算的系統容量時才會觸發系統保護(BBR 階段),系統容量由系統的
maxQps * minRt估算得出,設定參考值一般是CPU cores * 2.5, - 平均 RT:當單臺機器上所有入口流量的平均 RT 達到閾值即觸發系統保護,單位是毫秒,
- 并發執行緒數:當單臺機器上所有入口流量的并發執行緒數達到閾值即觸發系統保護,
- 入口 QPS:當單臺機器上所有入口流量的 QPS 達到閾值即觸發系統保護,
- CPU usage(1.5.0+ 版本):當系統 CPU 使用率超過閾值即觸發系統保護(取值范圍 0.0-1.0),比較靈敏,
8.2、規則演示
由于部分效果可能并不好測驗,本章節暫不演示,
第九章 Sentinel的保護模式
9.1、默認地址埋點保護
Sentinel為Spring Boot程式提供了一個starter依賴,由于Sentinel starter依賴默認情況下就會為所有的HTTP服務提供限流埋點,所以在Spring Boot中的Controller都可以受到Sentinel的保護,當然,我們還需要為Sentinel配置保護的規則,
他的底層是通過一個攔截器對請求url進行攔截:com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor
(1)重新啟動service-goods
(2)訪問地址:http://localhost:7001/goods/testA
(3)添加限流規則,如下圖:

(4)快速連續訪問地址:http://localhost:7001/goods/testA

(5)可以在application.yaml中,通過如下配置關閉對微服務的保護,然后重啟service-goods
server:
port: 7001
management:
endpoints:
web:
exposure:
include: '*'
spring:
cloud:
sentinel:
transport:
dashboard: http://localhost:8080
#關閉sentinel對controller的url的保護
filter:
enabled: false
(6)訪問地址:http://localhost:7001/goods/testA,無論你怎么訪問,你都會發現,控制臺根本就不顯示簇點鏈路的資訊了,如下圖:

9.2、手寫代碼埋點保護
我們在上一種方式中已經禁用了sentinel對controller的url的保護,接下來,我們將使用代碼的形式進行保護,
(1)修改service-goods的GoodsController的方法testB,然后重啟,代碼如下:
@RequestMapping("/goods/testB")
public String testB() {
Entry entry = null;
try {
entry = SphU.entry("testB");
//以下請書寫正常業務代碼...
return "server port:" + port + ",testB...";
} catch (Exception e) {
e.printStackTrace();
Tracer.trace(e);//記錄例外數量,對于例外比例和例外數的降級,這一句必須有
if (e instanceof FlowException) {
return "流量限流";//對應流控規則
} else if (e instanceof DegradeException) {
return "服務熔斷降級";//對應降級規則
} else if (e instanceof ParamFlowException) {
return "熱點引數限流";//對應熱點規則
} else if (e instanceof AuthorityException) {
return "黑白名單控制";//對應授權規則
} else if (e instanceof SystemBlockException) {
return "系統自適應限流";//對應系統規則
}
return "Exception ...";//上邊那一大串if...else也可以不寫,直接回傳這句
} finally {
if (entry != null) {
entry.exit();
}
}
}
(2)訪問地址:http://localhost:7001/goods/testB
(3)查看控制臺的簇點鏈路,如下圖:

(4)添加流控規則,如下圖:

(5)快速連續訪問地址:http://localhost:7001/goods/testB

我們也發現了,這種手寫代碼雖然也可以實作,而且代碼比較固定,雖然不難理解,但是會增加代碼的冗余,很不方便,于是就有了下邊這種注解方式,
9.3、使用注解埋點保護
官方說明:https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81
@SentinelResource 用于定義資源,并提供可選的例外處理和 fallback 配置項, @SentinelResource 注解包含以下屬性:
value:資源名稱,必需項(不能為空)entryType:entry 型別,可選項(默認為EntryType.OUT)blockHandler/blockHandlerClass:blockHandler對應處理BlockException的函式名稱,可選項,- 回傳值型別必須與原函式回傳值型別一致,并且函式訪問范圍需要是
public, - 方法引數串列需要和原函式一致,或者可以額外多一個
BlockException型別的引數用于接收對應的例外, - blockHandler 函式默認需要和原方法在同一個類中,若希望使用其他類的函式,則可以指定
blockHandlerClass為對應的類的Class物件,注意對應的函式必需為 static 函式,否則無法決議,
- 回傳值型別必須與原函式回傳值型別一致,并且函式訪問范圍需要是
fallback/fallbackClass:fallback 函式名稱,可選項,用于在拋出例外的時候提供 fallback 處理邏輯,fallback 函式可以針對所有型別的例外(除了exceptionsToIgnore里面排除掉的例外型別)進行處理,fallback 函式簽名和位置要求:- 回傳值型別必須與原函式回傳值型別一致,并且函式訪問范圍需要是
public, - 方法引數串列需要和原函式一致,或者可以額外多一個
Throwable型別的引數用于接收對應的例外, - fallback 函式默認需要和原方法在同一個類中,若希望使用其他類的函式,則可以指定
fallbackClass為對應的類的Class物件,注意對應的函式必需為 static 函式,否則無法決議,
- 回傳值型別必須與原函式回傳值型別一致,并且函式訪問范圍需要是
defaultFallback(since 1.6.0):默認的 fallback 函式名稱,可選項,通常用于通用的 fallback 邏輯(即可以用于很多服務或方法),默認 fallback 函式可以針對所有型別的例外(除了exceptionsToIgnore里面排除掉的例外型別)進行處理,若同時配置了 fallback 和 defaultFallback,則只有 fallback 會生效,defaultFallback 函式簽名要求:- 回傳值型別必須與原函式回傳值型別一致,并且函式訪問范圍需要是
public, - 方法引數串列需要為空,或者可以額外多一個
Throwable型別的引數用于接收對應的例外, - defaultFallback 函式默認需要和原方法在同一個類中,若希望使用其他類的函式,則可以指定
fallbackClass為對應的類的Class物件,注意對應的函式必需為 static 函式,否則無法決議,
- 回傳值型別必須與原函式回傳值型別一致,并且函式訪問范圍需要是
exceptionsToIgnore(since 1.6.0):用于指定哪些例外被排除掉,不會計入例外統計中,也不會進入 fallback 邏輯中,而是會原樣拋出,
注意:
- 1.6.0 之前的版本 fallback 函式只針對降級例外(
DegradeException)進行處理,不能針對業務例外進行處理, - 1.8.0 版本開始,
defaultFallback支持在類級別進行配置, - 注解方式埋點不支持 private 方法,
特別地,若 blockHandler 和 fallback 都進行了配置,則被限流降級而拋出 BlockException 時只會進入 blockHandler 處理邏輯,若未配置 blockHandler、fallback 和 defaultFallback,則被限流降級時會將 BlockException 直接拋出(若方法本身未定義 throws BlockException 則會被 JVM 包裝一層 UndeclaredThrowableException),
從 1.4.0 版本開始,注解方式定義資源支持自動統計業務例外,無需手動呼叫 Tracer.trace(ex) 來記錄業務例外,Sentinel 1.4.0 以前的版本需要自行呼叫 Tracer.trace(ex) 來記錄業務例外,
代碼演示
(1)撰寫Sentinel控制臺規則觸發的兜底兜底方法,全類名:com.caochenlei.controller.MyBlockHandler
public class MyBlockHandler {
public static String testC(@PathVariable("id") int id, BlockException blockException) {
return "testC:" + id + ",限流了,msg:" + blockException.getMessage();
}
}
(2)撰寫業務出錯兜底方法,全類名:com.caochenlei.controller.MyFallback
public class MyFallback {
public static String testC(@PathVariable("id") int id, Throwable t) {
return "testC:" + id + ",降級了,msg:" + t.getMessage();
}
}
(3)新增一個測驗方法,代碼如下:
@SentinelResource(value = "testC",
blockHandler = "testC", blockHandlerClass = MyBlockHandler.class,//這一對是處理sentinel規則的兜底方法
fallback = "testC", fallbackClass = MyFallback.class//這一對是處理當前控制器業務例外的熔斷降級的兜底方法
)
//下邊是你正常的業務邏輯和平時常用的注解,都不需要動,只需要單獨標注一個@SentinelResource注解,告訴Sentinel這是一個埋點資源
@RequestMapping("/goods/testC/{id}")
public String testC(@PathVariable("id") int id) {
//模擬業務正常
if (id == 1) {
return "server port:" + port + ",testC...";
}
//模擬業務出錯
if (id == 2) {
int i = 1 / 0;
}
return "other ...";
}
(4)訪問地址:http://localhost:7001/goods/testC/1

(5)添加流控規則,如下圖:

(6)快速連續訪問地址:http://localhost:7001/goods/testC/1

(7)測驗例外業務,看看會不會走兜底方法,訪問地址:http://localhost:7001/goods/testC/2

第十章 Sentinel與遠程呼叫
10.1、RestTemplate整合Sentinel
10.1.1、開啟Sentinel配置
修改service-goods的application.yaml,配置如下:
server:
port: 7001
management:
endpoints:
web:
exposure:
include: '*'
spring:
cloud:
sentinel:
transport:
dashboard: http://localhost:8080
#開啟sentinel對controller的url的保護
filter:
enabled: true
#開啟RestTemplate對Sentinel的支持,默認為true
resttemplate:
sentinel:
enabled: true
10.1.2、整合Sentinel注解
修改service-goods的ServiceGoodsApplication,代碼如下:
@SpringBootApplication
public class ServiceGoodsApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceGoodsApplication.class, args);
}
@SentinelRestTemplate(
//以下兩對配置可以不指定,不指定就使用默認的配置
fallback = "fallback", fallbackClass = SentinelRestTemplateExceptionUtil.class,
blockHandler = "blockHandler", blockHandlerClass = SentinelRestTemplateExceptionUtil.class
)
@LoadBalanced//負載均衡
@Bean//注冊組件
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
10.1.3、修改商品服務
(1)添加兜底處理類,類全名:com.caochenlei.controller.SentinelRestTemplateExceptionUtil
public class SentinelRestTemplateExceptionUtil {
//限流后處理
public static SentinelClientHttpResponse blockHandler
(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
return new SentinelClientHttpResponse("custom blockHandler info");
}
//降級后處理
public static SentinelClientHttpResponse fallback
(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
return new SentinelClientHttpResponse("custom fallback info");
}
}
(2)在GoodsController中添加新的測驗方法,代碼如下:
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/goods/testD/{id}")
public String testD(@PathVariable("id") int id) {
return restTemplate.getForObject("http://service-order/order/" + id, String.class);
}
(3)重新啟動service-goods
10.1.4、修改訂單服務
(1)在OrderController中添加新的測驗方法,代碼如下:
@RequestMapping("/order/{oid}")
public String find(@PathVariable("oid") int oid) {
//模擬正常業務
if (oid == 1) {
return "正常回傳訂單資訊";
}
//模擬例外業務
if (oid == 2) {
int i = 1 / 0;
}
return "other...";
}
(2)重新啟動service-order
10.1.5、訪問測驗地址
(1)快速連續多次訪問地址:http://localhost:7001/goods/testD/1

(2)快速連續多次訪問地址:http://localhost:7001/goods/testD/2

10.1.6、添加流控規則

10.1.7、添加降級規則

10.1.8、測驗最終效果
(1)快速連續多次訪問地址:http://localhost:7001/goods/testD/1

(2)快速連續多次訪問地址:http://localhost:7001/goods/testD/2

10.2、OpenFeign整合Sentinel
10.2.1、匯入相關依賴
在service-goods的pom.xml匯入相關依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
10.2.2、開啟相關配置
修改service-goods的application.yaml匯入相關配置:
server:
port: 7001
management:
endpoints:
web:
exposure:
include: '*'
spring:
cloud:
sentinel:
transport:
dashboard: http://localhost:8080
#開啟sentinel對controller的url的保護
filter:
enabled: true
#開啟RestTemplate對Sentinel的支持,默認為true
resttemplate:
sentinel:
enabled: true
#開啟feign對Sentinel的支持,默認為false
feign:
sentinel:
enabled: true
10.2.3、配置主啟動類
修改service-goods的ServiceGoodsApplication開啟Feign功能:
@SpringBootApplication
@EnableFeignClients // 開啟 Feign 功能
public class ServiceGoodsApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceGoodsApplication.class, args);
}
@SentinelRestTemplate(
//以下兩對配置可以不指定,不指定就使用默認的配置
fallback = "fallback", fallbackClass = SentinelRestTemplateExceptionUtil.class,
blockHandler = "blockHandler", blockHandlerClass = SentinelRestTemplateExceptionUtil.class
)
@LoadBalanced//負載均衡
@Bean//注冊組件
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
10.2.4、撰寫業務介面
(1)在service-goods下撰寫Feign的業務介面,呼叫遠程的服務是訂單服務,介面全名:com.caochenlei.service.FeignOrderService
@FeignClient(value = "service-order",fallback = FeignOrderServiceFallback.class)
public interface FeignOrderService {
@RequestMapping("/order/{oid}")
public String find(@PathVariable("oid") int oid);
}
(2)撰寫兜底的fallback類,類全名:com.caochenlei.service.FeignOrderServiceFallback
@Component
public class FeignOrderServiceFallback implements FeignOrderService{
@Override
public String find(int oid) {
return "FeignOrderServiceFallback 限流/降級...";
}
}
10.2.5、撰寫控制器類
在service-goods的GoodsController下,添加新的方法,代碼如下:
@Autowired
private FeignOrderService orderService;
@RequestMapping("/goods/testE/{id}")
public String testE(@PathVariable("id") int id) {
return orderService.find(id);
}
然后重新啟動service-goods
10.2.6、訪問測驗地址
(1)快速連續多次訪問地址:http://localhost:7001/goods/testE/1

(2)快速連續多次訪問地址:http://localhost:7001/goods/testE/2

10.2.7、添加流控規則

10.2.8、測驗流控規則
(1)快速連續多次訪問地址:http://localhost:7001/goods/testE/1

第十一章 Sentinel資料持久化
官方說明:https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel
一般來說,規則的推送有下面三種模式:
| 推送模式 | 說明 | 優點 | 缺點 |
|---|---|---|---|
| 原始模式 | API 將規則推送至客戶端并直接更新到記憶體中,擴展寫資料源(WritableDataSource) | 簡單,無任何依賴 | 不保證一致性;規則保存在記憶體中,重啟即消失,嚴重不建議用于生產環境 |
| Pull 模式 | 擴展寫資料源(WritableDataSource), 客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS、檔案 等 | 簡單,無任何依賴;規則持久化 | 不保證一致性;實時性不保證,拉取過于頻繁也可能會有性能問題, |
| Push 模式 | 擴展讀資料源(ReadableDataSource),規則中心統一推送,客戶端通過注冊監聽器的方式時刻監聽變化,比如使用 Nacos、Zookeeper 等配置中心,這種方式有更好的實時性和一致性保證,生產環境下一般采用 push 模式的資料源, | 規則持久化;一致性;快速 | 引入第三方依賴 |
11.1、原始模式
如果不做任何修改,Dashboard 的推送規則方式是通過 API 將規則推送至客戶端并直接更新到記憶體中:

這種做法的好處是簡單,無依賴;壞處是應用重啟規則就會消失,僅用于簡單測驗,不能用于生產環境,
11.2、Pull模式
ull 模式的資料源(如本地檔案、RDBMS 等)一般是可寫入的,使用時需要在客戶端注冊資料源:將對應的讀資料源注冊至對應的 RuleManager,將寫資料源注冊至 transport 的 WritableDataSourceRegistry 中,以本地檔案資料源為例:
public class FileDataSourceInit implements InitFunc {
@Override
public void init() throws Exception {
String flowRulePath = "xxx";
ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(
flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
);
// 將可讀資料源注冊至 FlowRuleManager.
FlowRuleManager.register2Property(ds.getProperty());
WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);
// 將可寫資料源注冊至 transport 模塊的 WritableDataSourceRegistry 中.
// 這樣收到控制臺推送的規則時,Sentinel 會先更新到記憶體,然后將規則寫入到檔案中.
WritableDataSourceRegistry.registerFlowDataSource(wds);
}
private <T> String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
本地檔案資料源會定時輪詢檔案的變更,讀取規則,這樣我們既可以在應用本地直接修改檔案來更新規則,也可以通過 Sentinel 控制臺推送規則,以本地檔案資料源為例,推送程序如下圖所示:

首先 Sentinel 控制臺通過 API 將規則推送至客戶端并更新到記憶體中,接著注冊的寫資料源會將新的規則保存到本地的檔案中,使用 pull 模式的資料源時一般不需要對 Sentinel 控制臺進行改造,
這種實作方法好處是簡單,不引入新的依賴,壞處是無法保證監控資料的一致性,
11.2.1、撰寫代碼
在service-goods下創建類com.caochenlei.FileDataSourceInit
/**
* 規則持久化
*/
public class FileDataSourceInit implements InitFunc {
@Override
public void init() throws Exception {
//可以根據需要指定規則檔案的位置
String ruleDir = System.getProperty("user.home") + "/sentinel/rules";
String flowRulePath = ruleDir + "/flow-rule.json";
String degradeRulePath = ruleDir + "/degrade-rule.json";
String paramFlowRulePath = ruleDir + "/param-flow-rule.json";
String systemRulePath = ruleDir + "/system-rule.json";
String authorityRulePath = ruleDir + "/authority-rule.json";
this.mkdirIfNotExits(ruleDir);
this.createFileIfNotExits(flowRulePath);
this.createFileIfNotExits(degradeRulePath);
this.createFileIfNotExits(paramFlowRulePath);
this.createFileIfNotExits(systemRulePath);
this.createFileIfNotExits(authorityRulePath);
// 流控規則:可讀資料源
ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(
flowRulePath,
flowRuleListParser
);
// 將可讀資料源注冊至FlowRuleManager
// 這樣當規則檔案發生變化時,就會更新規則到記憶體
FlowRuleManager.register2Property(flowRuleRDS.getProperty());
// 流控規則:可寫資料源
WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
flowRulePath,
this::encodeJson
);
// 將可寫資料源注冊至transport模塊的WritableDataSourceRegistry中
// 這樣收到控制臺推送的規則時,Sentinel會先更新到記憶體,然后將規則寫入到檔案中
WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
// 降級規則:可讀資料源
ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(
degradeRulePath,
degradeRuleListParser
);
DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
// 降級規則:可寫資料源
WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(
degradeRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
// 熱點引數規則:可讀資料源
ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new FileRefreshableDataSource<>(
paramFlowRulePath,
paramFlowRuleListParser
);
ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
// 熱點引數規則:可寫資料源
WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(
paramFlowRulePath,
this::encodeJson
);
ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
// 系統規則:可讀資料源
ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(
systemRulePath,
systemRuleListParser
);
SystemRuleManager.register2Property(systemRuleRDS.getProperty());
// 系統規則:可寫資料源
WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(
systemRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
// 授權規則:可讀資料源
ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>(
authorityRulePath,
authorityRuleListParser
);
AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
// 授權規則:可寫資料源
WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(
authorityRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);
}
private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(
source,
new TypeReference<List<FlowRule>>() {}
);
private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(
source,
new TypeReference<List<DegradeRule>>() {}
);
private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(
source,
new TypeReference<List<SystemRule>>() {}
);
private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject(
source,
new TypeReference<List<AuthorityRule>>() {}
);
private Converter<String, List<ParamFlowRule>> paramFlowRuleListParser = source -> JSON.parseObject(
source,
new TypeReference<List<ParamFlowRule>>() {}
);
private void mkdirIfNotExits(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists()) {
file.mkdirs();
}
}
private void createFileIfNotExits(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists()) {
file.createNewFile();
}
}
private <T> String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
11.2.2、配置代碼
在service-goods的resources下創建檔案夾META-INF\services,然后創建檔案:META-INF\services\com.alibaba.csp.sentinel.init.InitFunc
com.caochenlei.FileDataSourceInit
11.2.3、重啟工程
重新啟動service-goods,然后訪問地址:http://localhost:7001/goods/testA

11.2.4、添加流控規則

我們這一章主要學習如何持久化,而不是各種限流測驗,添加規則以后,我們就會發現規則已經持久化到了本地指定檔案中了

11.2.5、添加降級規則

我們這一章主要學習如何持久化,而不是各種限流測驗,添加規則以后,我們就會發現規則已經持久化到了本地指定檔案中了

11.2.6、添加熱點規則

我們這一章主要學習如何持久化,而不是各種限流測驗,添加規則以后,我們就會發現規則已經持久化到了本地指定檔案中了

11.2.7、添加授權規則

我們這一章主要學習如何持久化,而不是各種限流測驗,添加規則以后,我們就會發現規則已經持久化到了本地指定檔案中了

11.2.8、添加系統規則

我們這一章主要學習如何持久化,而不是各種限流測驗,添加規則以后,我們就會發現規則已經持久化到了本地指定檔案中了

11.2.9、重啟以后查看
重新啟動service-goods,然后訪問地址:http://localhost:7001/goods/testA

流控規則

降級規則

熱點規則

授權規則

系統規則

為了下一小節的演示,請將META-INF\services\com.alibaba.csp.sentinel.init.InitFunc里邊的內容洗掉,然后重啟檢查發現規則已經全部取消,
11.3、Push模式
生產環境下一般更常用的是 push 模式的資料源,對于 push 模式的資料源,如遠程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不應由 Sentinel 客戶端進行,而應該經控制臺統一進行管理,直接進行推送,資料源僅負責獲取配置中心推送的配置并更新到本地,因此推送規則正確做法應該是 配置中心控制臺/Sentinel 控制臺 → 配置中心 → Sentinel 資料源 → Sentinel,而不是經 Sentinel 資料源推送至配置中心,這樣的流程就非常清晰了:

我們提供了 ZooKeeper, Apollo, Nacos 等的動態資料源實作,以 ZooKeeper 為例子,如果要使用第三方的配置中心作為配置管理,您需要做下面的幾件事情:
- 實作一個公共的 ZooKeeper 客戶端用于推送規則,在 Sentinel 控制臺配置項中需要指定 ZooKeeper 的地址,啟動時即創建 ZooKeeper Client,
- 我們需要針對每個應用(appName),每種規則設定不同的 path(可隨時修改);或者約定大于配置(如 path 的模式統一為
/sentinel_rules/{appName}/{ruleType},e.g.sentinel_rules/appA/flowRule), - 規則配置頁需要進行相應的改造,直接針對應用維度進行規則配置;修改同個應用多個資源的規則時可以批量進行推送,也可以分別推送,Sentinel 控制臺將規則快取在記憶體中(如
InMemFlowRuleStore),可以對其進行改造使其支持應用維度的規則快取(key 為 appName),每次添加/修改/洗掉規則都先更新記憶體中的規則快取,然后需要推送的時候從規則快取中獲取全量規則,然后通過上面實作的 Client 將規則推送到 ZooKeeper 即可, - 應用客戶端需要注冊對應的讀資料源以監聽變更,可以參考 相關檔案,
從 Sentinel 1.4.0 開始,Sentinel 控制臺提供 DynamicRulePublisher 和 DynamicRuleProvider 介面用于實作應用維度的規則推送和拉取,并提供了相關的示例,Sentinel 提供應用維度規則推送的示例頁面(/v2/flow),用戶改造控制臺對接配置中心后可直接通過 v2 頁面推送規則至配置中心,改造詳情可參考 應用維度規則推送示例,
部署多個控制臺實體時,通常需要將規則存至 DB 中,規則變更后同步向配置中心推送規則,
11.3.1、匯入依賴
在service-goods的pom.xml中新增以下依賴:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
11.3.2、撰寫配置
在service-goods的application.yaml修改成如下配置:
server:
port: 7001
management:
endpoints:
web:
exposure:
include: '*'
spring:
cloud:
sentinel:
transport:
dashboard: http://localhost:8080
#開啟sentinel對controller的url的保護
filter:
enabled: true
datasource:
ds1:
nacos:
serverAddr: ${spring.cloud.nacos.discovery.server-addr}
dataId: flow-rule.json
groupId: DEFAULT_GROUP
dataType: json
ruleType: flow
ds2:
nacos:
serverAddr: ${spring.cloud.nacos.discovery.server-addr}
dataId: degrade-rule.json
groupId: DEFAULT_GROUP
dataType: json
ruleType: degrade
ds3:
nacos:
serverAddr: ${spring.cloud.nacos.discovery.server-addr}
dataId: param-flow-rule.json
groupId: DEFAULT_GROUP
dataType: json
ruleType: param-flow
ds4:
nacos:
serverAddr: ${spring.cloud.nacos.discovery.server-addr}
dataId: authority-rule.json
groupId: DEFAULT_GROUP
dataType: json
ruleType: authority
ds5:
nacos:
serverAddr: ${spring.cloud.nacos.discovery.server-addr}
dataId: system-rule.json
groupId: DEFAULT_GROUP
dataType: json
ruleType: system
#開啟RestTemplate對Sentinel的支持,默認為true
resttemplate:
sentinel:
enabled: true
#開啟feign對Sentinel的支持,默認為false
feign:
sentinel:
enabled: true
11.3.3、創建檔案
訪問地址:http://localhost:8848/nacos/,登錄賬號:nacos,登錄密碼:nacos

依次創建如下檔案,檔案內容拷貝之前生成到本地的內容資料即可,


11.3.4、重啟應用
重新啟動service-goods,然后訪問地址:http://localhost:7001/goods/testA

流控規則

降級規則

熱點規則

授權規則

系統規則

你修改了以后是不能保存到nacos配置中心的,關于這個問題,可能會在以后的版本中進行增強,
第十二章 Sentinel的其他流控
12.1、集群流控
官方說明:https://github.com/alibaba/Sentinel/wiki/%E9%9B%86%E7%BE%A4%E6%B5%81%E6%8E%A7
12.2、網關流控
官方說明:https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/262181.html
標籤:其他
下一篇:Java開發設計——七大原則
