初始Sentinel來學習SpringCloud Alibaba的元件-熔斷服務降級
Sentinel簡介
Sentinel 是面向分布式服務架構的高可用流量防護元件
,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個次元來幫助開發者保障微服務的穩定性。
文章目錄
- Sentinel簡介
- 一、前言
- 1. Sentinel的特點
- 2. 服務可用性問題
- 2.1 服務雪崩
- 2.2 常見的容錯機制
- 2.2.1 逾時機制
- 2.2.2 服務限流
- 2.2.3 隔離
- 二、Sentinel概念解釋
- 1.流量控制
- 2.熔斷降級
- 3. 系統保護
- 三、NacosConfig快速開始
- 3.1 引入依賴
- 3.2 建立配置檔案
- 3.3 建立一個HelloWorldController的檔案
- 3.4 啟動服務,通路
一、前言
1. Sentinel的特點
Sentinel 具有以下特性:
- 豐富的應用場景: Sentinel 承接了阿裡巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峰填谷、叢集流量控制、實時熔斷下遊不可用應用等。
- 完備的實時監控: Sentinel 同時提供實時的監控功能。您可以在控制台中看到接入應用的單台機器秒級資料,甚至 500 台以下規模的叢集的彙總運作情況。
- 廣泛的開源生态: Sentinel 提供開箱即用的與其它開源架構 / 庫的整合子產品,例如與 Spring Cloud、Dubbo、gRPC 的整合。您隻需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel。
- 完善的 SPI 擴充點: Sentinel 提供簡單易用、完善的 SPI 擴充接口。您可以通過實作擴充接口來快速地定制邏輯。例如定制規則管理、适配動态資料源等。
2. 服務可用性問題
❓思考:當我們的服務挂掉的時候,我們首先考慮什麼原因
- 激增流量打垮伺服器
- 被其它服務搞垮
- 異常沒有處理
總而言之: 就是缺乏高可用的防護/容錯機制,尤其是針對流量的防護
2.1 服務雪崩
服務雪崩:就是指當在分布式 的微服務系統中,我們的有一個微服務A調用了微服務B和C,微服務B又調用了微服務D和E…;這個過程在軟體工程你學上有一個專業的術語:
扇出
:
;
扇出:一個子產品直接調用的下級子產品
扇入:一個子產品被直接調用的上級子產品
在某一個時刻,在該子產品的删除鍊路上的某一個子產品請求的時間過長或者服務出現了錯誤,造成了該子產品的某個執行個體不可用,那麼此時,你就會發現微服務A會越來越占用計算機資源,進而導緻系統越來越卡,延遲,等一系列的問題就接踵而至。這種由某一個子服務的失效而導緻的整個服務體系的崩潰問題
但是,對于對于高流量的系統應用而言,某一個依賴可能會導緻所有伺服器上的所有資源都在幾秒内飽和,比失敗更糟糕的是,這些應用程式還可能導緻服務之間的延遲增加,備份隊列,線程和其他資源緊張,這樣會導緻很多蝴蝶效應。但是我們不能統一的整體管理,隻能對某個失敗的執行個體進行隔離和單獨管理,以便單個依賴關系的失敗,不能取消整個應用程式或系統。
總結: 因為服務提供者的不可用而導緻服務調用者的不可用,并逐漸放大的過程,這個過程就叫做服務雪崩效應。
2.2 常見的容錯機制
2.2.1 逾時機制
在不做出任何處理得情況下,服務提供者不可用會導緻消費者請求線程強制停止,而造成系統資源耗盡,加入逾時機制,一旦逾時,就釋放資源。由于資源釋放速度快。一定程度上可以抑制資源的消耗的問題。
2.2.2 服務限流
2.2.3 隔離
原理:使用者的請求将不在直接的通路服務,而是通過線程中的空閑線程來通路,如果線程池已滿,則會通過服務降級來處理,使用者的請求不會阻塞,至少有一個執行結果(例如傳回友好的提示資訊,而不是通過無休止的等待或者是系統崩潰)
隔離前:
隔離後:
二、Sentinel概念解釋
1.流量控制
流控:流量控制,即根據流量數,并發線程數目,響應時間等,來對随即到來的流量進行調整成合适的形狀,叫做
流量塑性
流量控制有以下幾個角度:
- 運作名額,例如QPS、并發線程數等。
- 資源的調用關系,例如資源的調用鍊路,資源和資源之間的關系,調用來源等。
- 控制效果,例如排隊等待、直接拒絕、Warm Up(預熱)等。
2.熔斷降級
除流量控制以外,對調用鍊路中不穩定的資源進行熔斷降級也是保障高可用的重要措施之一。
由于調用關系的複雜性,如果調用鍊路中的某個資源不穩定,最終會導緻請求發生堆積。熔斷降級會在調用鍊路中某個資源出現不穩定狀态時(例如調用逾時或異常比例升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導緻級聯錯誤。
Sentinel 熔斷降級支援以下幾種 熔斷政策:
- 秒級 RT 模式:若持續進入 5 個請求,它們資源的平均響應時間都超過門檻值(秒級平均 RT,以 ms 為機關),資源調用會被熔斷。在接下的降級時間視窗(在降級規則中配置,以 s 為機關)之内,對這個方法的調用都會自動地傳回(抛出 DegradeException)。
- 秒級異常比例模式:當資源的每秒異常數占通過量的比值超過門檻值之後,資源進入降級狀态,即在接下的降級時間視窗(在降級規則中配置,以 s 為機關))之内,對這個方法的調用都會自動地傳回。異常比率的門檻值範圍是 [0.0, 1.0],代表 0% - 100%。
- 分鐘級異常數模式:當資源最近 1 分鐘的異常數目超過門檻值之後會進行熔斷。
再生活中,我們最常見到的熔斷機制就是我們的保險絲,當家裡的電燈泡,如果出現溫度過高,會把保險絲燒斷,這樣一來就保護了燈泡不會爆掉,進而避免的危險,
在一個即使我們炒股,股市的漲停與跌停,保證股民的風險在一定的範圍内。以便留出足夠的時間去修複
在我們的軟體行業裡,我們使用熔斷機制來保證一個微服務被挂掉之後,會立刻将其殺掉,保證其他服務的正常營運和避免一些列的級聯影響,使得影響降到最低。
服務降級發生的依賴場所: 我們服務降級通常是發生在弱依賴的關系鍊上
所謂的弱依賴就是指當我們的這個服務挂掉以後,不會對我們的整個服務造成影響
3. 系統保護
系統保護機制從整體次元對應用入口流量進行控制,結合應用的Load、總體平均RT、入口QPS和線程數等幾個次元的監控名額,讓系統的入口流量和系統的負載達到一個平衡,對多餘的流量直接拒絕,讓系統盡可能維持在最大吞吐量的同時保證系統整體的穩定性。
❓說明 系統保護規則是整體次元的,而不是資源次元的,并且僅對入口流量生效。入口流量指的是進入應用的流量,比如Web服務或Dubbo服務端接收的請求,都屬于入口流量。
對于一個應用來說,每種相同的系統保護規則最多隻能存在一條,即一個應用最多配置五條系統保護規則。
系統規則支援五種門檻值類型:
- Load(僅對Linux、Unix-like機器生效):當系統load1超過門檻值,且系統目前的并發線程數超過預計的系統容量時才會觸發系統保護。預計的系統容量由系統的maxQps * minRt計算得出。
- CPU使用率:當系統CPU使用率超過門檻值(0.0~1.0)即觸發系統保護。
- RT:當單台機器上所有入口流量的平均RT達到門檻值即觸發系統保護,機關是毫秒。
- 線程數:當單台機器上所有入口流量的并發線程數達到門檻值即觸發系統保護。
- 入口QPS:當單台機器上所有入口流量的QPS達到門檻值即觸發系統保護。
QPS:每秒查詢率
常見的熔斷器的對比
Sentnel | HyStrix | |
隔離政策 | 信号量隔離 | 線程池隔離/信号量隔離 |
熔斷降級政策 | 給予響應時間的或者失敗比例 | 基于失敗比例 |
實施名額實作 | 滑動視窗 | 滑動視窗 |
規則配置 | 支援多種資料源 | 支援多種資料源 |
擴充性 | 多個擴充點 | 插件的形式 |
基于注解的支援 | 支援 | 支援 |
限流 | 基于QPS,支援基于調用關系的限流 | 有限的形式 |
流量整形 | 支援慢啟動,勻速器模式 | 不支援 |
系統負載保護 | 支援 | 不支援 |
控制台 | 開箱即用,可配置規則,檢視秒級監控,及其發現等 | 不完善 |
常見架構的适配 | Servlet,Spring Cloud, Dubbo,Grpc | Servlet,SPringleCloud Netfix |
三、NacosConfig快速開始
官網位址:https://sentinelguard.io/zh-cn/ 在官方文檔中,定義的Sentinel進行資源保護的幾個步驟:
參考:https://sentinelguard.io/zh-cn/docs/basic-api-resource-rule.html
- 定義資源
- 定義規則
【流控規則;降級規則】
- 檢查規則是否生效
3.1 引入依賴
父工程的依賴
<!--同一版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.11.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
<springcloudalibaba.version>2.2.4.RELEASE</springcloudalibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springcloud alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${springcloudalibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- springBoot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
詳細的版本資訊,可以參考我的Nacos第一篇
子服務的pom依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
使用的是Sentinel的1.8.0版本
3.2 建立配置檔案
server:
port: 8090
servlet:
context-path: "/"
規定服務的端口号和通路位址等資訊
3.3 建立一個HelloWorldController的檔案
@RestController
public class HelloWorldController {
@RequestMapping("/hello")
public String helloWorld() {
try (Entry entry = SphU.entry("Hello World")){ // 使用限流規則 限流資源為Hello World
return "Sentinel 馬冬梅 你好!!"+System.currentTimeMillis();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return "系統繁忙,行了大爺 您先涼快會吧!!!"; // 降級處理
}
}
/**
* 定義限流規則
* PostContruct 構造方法執行完後執行方法 定義和加載限流規則
*/
@PostConstruct
public void initFlowRules() {
List<FlowRule> rules = new ArrayList<>(); // 定義先流規則集合
FlowRule rule = new FlowRule(); // 定義限流規則
rule.setResource("Hello World"); // 定義限流資源
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 定義限流規則類型 QPS查詢率
rule.setCount(2); // 定義QPS門檻值 每秒最多查詢2個請求個數
rules.add(rule); // 添加規則集合
FlowRuleManager.loadRules(rules); // 加載規則集合
}
}
書寫步驟嚴格遵循上面所講的步驟,且配置細節參考官方文檔
3.4 啟動服務,通路
正常通路1s通路次數不超過2次