什麼是sentinel?
Sentinel: 分布式系統的流量防衛兵
Sentinel 具有以下特征:
- 豐富的應用場景:Sentinel 承接了阿裡巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峰填谷、叢集流量控制、實時熔斷下遊不可用應用等。
- 完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制台中看到接入應用的單台機器秒級資料,甚至 500 台以下規模的叢集的彙總運作情況。
-
廣泛的開源生态:Sentinel 提供開箱即用的與其它開源架構/庫的整合子產品,例如與 Spring Cloud、Dubbo、gRPC 的整合。您隻需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel。
完善的 SPI 擴充點:Sentinel 提供簡單易用、完善的 SPI 擴充接口。您可以通過實作擴充接口來快速地定制邏輯。例如定制規則管理、适配動态資料源等。
Sentinel 的主要特性:
Sentinel 分為兩個部分:
- 核心庫(Java 用戶端)不依賴任何架構/庫,能夠運作于所有 Java 運作時環境,同時對 Dubbo / Spring Cloud 等架構也有較好的支援。
- 控制台(Dashboard)基于 Spring Boot 開發,打包後可以直接運作,不需要額外的 Tomcat 等應用容器。
github位址
中文介紹
安裝Sentinel
- 首先去下載下傳,位址
- 然後運作,運作指令
java -jar sentinel-dashboard-1.8.2.jar
前提是有jdk環境,并且8080端口不能被占用
然後去通路
http://localhost:8080
使用者名密碼都是sentinel
使用者名密碼都是sentinel
項目整合sentinel
- 建立子產品
cloudalibaba-sentinel-service8401
- 修改pom檔案,添加以下的依賴
<dependencies>
<dependency><!-- 引入自己定義的api通用包,可以使用Payment支付Entity -->
<groupId>com.zhubayi.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos 後續做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringBoot整合Web元件+actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 修改配置檔案
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
#Nacos服務注冊中心位址
server-addr: localhost:8848
sentinel:
transport:
#配置Sentinel dashboard位址
dashboard: localhost:8080
#預設8719端口,假如被占用會自動從8719開始依次+1掃描,直至找到未被占用的端口
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
- 建立
主啟動類MainApp8401
package com.zhubayi.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401
{
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}
- 建立
類FlowLimitController
package com.zhubayi.springcloud.alibaba.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController
{
@GetMapping("/testA")
public String testA()
{
return "------testA";
}
@GetMapping("/testB")
public String testB()
{
return "------testB";
}
}
然後啟動Sentinel8080
java -jar sentinel-dashboard-1.8.2.jar
登入進去發現啥都沒有
因為Sentinel采用的懶加載,當有通路時才會加載,是以執行一次通路即可
http://localhost:8401/testA
http://localhost:8401/testB
說明sentinel8080正在監控微服務8401。
流控規則
1.基本介紹
解釋說明:
2. 流控模式
(1) 直接(預設)
- 就是快速失敗,直接不讓通路了,這是
的系統預設
- 配置說明
表示1秒鐘内查詢1次就是OK,若超過次數1,就直接-快速失敗,報預設錯誤
表示1秒鐘内查詢1次就是OK,若超過次數1,就直接-快速失敗,報預設錯誤
測試:快速點選通路
http://localhost:8401/testA
直接調用預設報錯資訊
(2) 關聯
關聯是啥意思?
- 當關聯的資源達到門檻值時,就限流自己。例如:當與A關聯的資源B達到閥值後,就限流A自己。B惹事,A挂了
- 配置A
說明:當關聯資源/testB的qps閥值超過1時,就限流/testA的Rest通路位址,當關聯資源到門檻值後限制配置好的資源名
說明:當關聯資源/testB的qps閥值超過1時,就限流/testA的Rest通路位址,當關聯資源到門檻值後限制配置好的資源名
postman模拟并發密集通路testB
開始運作然後去通路
testA
可以看出,大批量線程高并發通路B,導緻A失效了
(3) 鍊路
鍊路流控模式指的是,當從某個接口過來的資源達到限流條件時,開啟限流。它的功能有點類似于針對來源配置項,差別在于:針對來源是針對上級微服務,而鍊路流控是針對上級接口,也就是說它的粒度更細。
這是重點講的内容 畢竟在這裡踩過坑
我用的版本是springCloud-alibab 是2.2.5.RELEASE sentinel1.8.0 是以會造成流控鍊路失效
給出解決辦法
Sentinel 鍊路流控模式失效
禁止收斂URL的入口context
從1.6.3 版本開始,Sentinel Web filter預設收斂所有URL的入口context,是以鍊路限流不生效。
1.7.0 版本開始(對應SCA的2.1.1.RELEASE),官方在CommonFilter 引入了
WEB_CONTEXT_UNIFY 參數,用于控制是否收斂context。将其配置為 false 即可根據不同的URL 進行鍊路限流。
SCA 2.1.1.RELEASE之後的版本,可以通過配置spring.cloud.sentinel.web-context-unify=false即可關閉收斂
我們目前使用的版本是SpringCloud Alibaba 2.2.5.RELEASE,無法實作鍊路限流。
新增service接口
package com.zhubayi.springcloud.alibaba.serivce;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;
@Service
public class MySentinelService {
/**
* @SentinelResource: 可以了解就是一個資源名
*/
@SentinelResource(value = "myresource",blockHandler = "testAFallback")
public String sentinelChain() {
return "調用該資源成功!!!!!";
}
public String testAFallback(BlockException ex) {
return "ex testA";
}
}
- controller
package com.zhubayi.springcloud.alibaba.controller;
import com.zhubayi.springcloud.alibaba.serivce.MySentinelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController
{
@Autowired
private MySentinelService mySentinelService;
@GetMapping("/testA")
public String testA()
{
return "------testA"+mySentinelService.sentinelChain();
}
@GetMapping("/testB")
public String testB()
{
return "------testB"+mySentinelService.sentinelChain();
}
}
如果單單是這樣的配置 是不起效果的 還需要新增配置
1.7.0 版本開始(對應Spring Cloud Alibaba的2.1.1.RELEASE) 需要新增依賴
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
</dependency>
然後配置
spring.cloud.sentinel.web-context-unify=false
配置類
FilterContextConfig
package com.zhubayi.springcloud.alibaba.config;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterContextConfig {
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new CommonFilter());
registrationBean.addUrlPatterns("/*");
// 入口資源關閉聚合
registrationBean.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
registrationBean.setName("sentinelFilter");
registrationBean.setOrder(1);
return registrationBean;
}
}
接下來就有效果了
測試:頻繁通路testA會報錯,而通路testB則無影響。
3.流控效果
(1)直接->快速失敗
- 這時預設的處理方式,預設的流控處理
- 直接失敗,抛出異常->Blocked by Sentinel (flow limiting)
- 源碼:
com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
(2) Warm up 預熱
當流量突然增大的時候,我們常常會希望系統從空閑狀态到繁忙狀态的切換的時間長一些。即如果系統在此之前長期處于空閑的狀态,我們希望處理請求的數量是緩步的增多,經過預期的時間以後,到達系統處理請求個數的最大值。Warm Up(冷啟動,預熱)模式就是為了實作這個目的的。
預設 coldFactor 為 3,即請求 QPS 從 threshold / 3 開始,經預熱時長逐漸升至設定的 QPS 門檻值。
公式:門檻值除以coldFactor(預設值為3),經過預熱時長後才會達到門檻值
例如:
上面的是官方說法 說人話就是
10/3=3
,即剛開始的門檻值為3
你一開始請求超過
每秒3次
則報錯 等預熱
5秒鐘
,5秒之後,
超過每秒10次
系統報錯,若不超過每秒10次,則正常運作
比如你要跑100米 得先熱熱身 讓身體适應一下 不然抽筋猝死就gg了
應用場景: 秒殺系統在開啟的瞬間,會有很多流量上來,很有可能把系統打死,預熱方式就是把為了保護系統,可慢慢的把流量放進來,慢慢的把閥值增長到設定的閥值。
官方冷啟動說明
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即預熱/冷啟動方式。當系統長期處于低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間内逐漸增加到門檻值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。詳細文檔可以參考 流量控制 - Warm Up 文檔,具體的例子可以參見 WarmUpFlowDemo。
通常冷啟動的過程系統允許通過的 QPS 曲線如下圖所示:
(3)排隊等待
官方文檔
勻速排隊(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法。詳細文檔可以參考 流量控制 - 勻速器模式,具體的例子可以參見 PaceFlowDemo。
該方式的作用如下圖所示:
這種方式主要用于處理間隔性突發的流量,例如消息隊列。想象一下這樣的場景,在某一秒有大量的請求到來,而接下來的幾秒則處于空閑狀态,我們希望系統能夠在接下來的空閑期間逐漸處理這些請求,而不是在第一秒直接拒絕多餘的請求。
注意:勻速排隊模式暫時不支援 QPS > 1000 的場景。
例如:
說明:
勻速排隊,讓請求以均勻的速度通過,閥值類型必須設成QPS,否則無效。
設定含義:/testA每秒1次請求,超過的話就排隊等待,等待的逾時時間為20000毫秒,超過則報錯。