主頁 > 軟體設計 > 服務熔斷與限流:Sentinel

服務熔斷與限流:Sentinel

2021-02-22 12:51:22 軟體設計

目錄

  • 第一章 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的對比

SentinelHystrixresilience4j
隔離策略信號量隔離(并發控制)執行緒池隔離/信號量隔離信號量隔離
熔斷降級策略基于慢呼叫比例、例外比例、例外數基于例外比例基于例外比例、回應時間
實時統計實作滑動視窗(LeapArray)滑動視窗(基于 RxJava)Ring Bit Buffer
動態規則配置支持近十種動態資料源支持多種資料源有限支持
擴展性多個擴展點插件的形式介面的形式
基于注解的支持支持支持支持
單機限流基于 QPS,支持基于呼叫關系的限流有限的支持Rate Limiter
集群流控支持不支持不支持
流量整形支持預熱模式與勻速排隊控制效果不支持簡單的 Rate Limiter 模式
系統自適應保護支持不支持不支持
熱點識別/防護支持不支持不支持
多語言支持Java/Go/C++JavaJava
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-goodspom.xml中新增如下依賴:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

3.2.2、新增配置

service-goodsapplication.yaml中新增如下配置:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: http://localhost:8080

service-goodsbootstrap.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)添加流控規則,如下圖:

image-20210219195150778

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

NodeSelectorSlot 中記錄了資源之間的呼叫鏈路,這些資源通過呼叫關系,相互之間構成一棵呼叫樹,這棵樹的根節點是一個名字為 machine-root 的虛擬節點,呼叫鏈的入口都是這個虛節點的子節點,

一棵典型的呼叫樹如下圖所示:

     	          machine-root
                    /       \
                   /         \
             Entrance1     Entrance2
                /             \
               /               \
      DefaultNode(nodeA)   DefaultNode(nodeA)

上圖中來自入口 Entrance1Entrance2 的請求都呼叫到了資源 NodeA,Sentinel 允許只根據某個入口的統計資訊對資源限流,比如我們可以設定 strategyRuleConstant.STRATEGY_CHAIN,同時設定 refResourceEntrance1 來表示只有從入口 Entrance1 的呼叫才會記錄到 NodeA 的限流統計當中,而不關心經 Entrance2 到來的呼叫,

同理,我們現在對/goods/testB的限流都是經過sentinel_spring_web_context這個虛擬節點的,如下圖:

4.2.4、流控效果:快速失敗

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

4.2.5、流控效果:Warm Up

Warm UpRuleConstant.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-goodsGoodsControllerfindByGid方法,然后重啟,代碼如下:

@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-goodsGoodsControllerfindByGid方法,然后重啟,代碼如下:

@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

image-20210220180200233

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-goodsGoodsController的方法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 處理邏輯,若未配置 blockHandlerfallbackdefaultFallback,則被限流降級時會將 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-goodsapplication.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-goodsServiceGoodsApplication,代碼如下:

@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-goodspom.xml匯入相關依賴:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

10.2.2、開啟相關配置

修改service-goodsapplication.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-goodsServiceGoodsApplication開啟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-goodsGoodsController下,添加新的方法,代碼如下:

@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-goodsresources下創建檔案夾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 為例子,如果要使用第三方的配置中心作為配置管理,您需要做下面的幾件事情:

  1. 實作一個公共的 ZooKeeper 客戶端用于推送規則,在 Sentinel 控制臺配置項中需要指定 ZooKeeper 的地址,啟動時即創建 ZooKeeper Client,
  2. 我們需要針對每個應用(appName),每種規則設定不同的 path(可隨時修改);或者約定大于配置(如 path 的模式統一為 /sentinel_rules/{appName}/{ruleType},e.g. sentinel_rules/appA/flowRule),
  3. 規則配置頁需要進行相應的改造,直接針對應用維度進行規則配置;修改同個應用多個資源的規則時可以批量進行推送,也可以分別推送,Sentinel 控制臺將規則快取在記憶體中(如 InMemFlowRuleStore),可以對其進行改造使其支持應用維度的規則快取(key 為 appName),每次添加/修改/洗掉規則都先更新記憶體中的規則快取,然后需要推送的時候從規則快取中獲取全量規則,然后通過上面實作的 Client 將規則推送到 ZooKeeper 即可,
  4. 應用客戶端需要注冊對應的讀資料源以監聽變更,可以參考 相關檔案,

從 Sentinel 1.4.0 開始,Sentinel 控制臺提供 DynamicRulePublisherDynamicRuleProvider 介面用于實作應用維度的規則推送和拉取,并提供了相關的示例,Sentinel 提供應用維度規則推送的示例頁面(/v2/flow),用戶改造控制臺對接配置中心后可直接通過 v2 頁面推送規則至配置中心,改造詳情可參考 應用維度規則推送示例,

部署多個控制臺實體時,通常需要將規則存至 DB 中,規則變更后同步向配置中心推送規則,

11.3.1、匯入依賴

service-goodspom.xml中新增以下依賴:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

11.3.2、撰寫配置

service-goodsapplication.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

標籤:其他

上一篇:pulsar分析以及各訊息佇列對比

下一篇:Java開發設計——七大原則

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more