SpringCloud Alibaba Sentinel 從入門到精通
前言
在微服務架構中,服務間的依賴關系復雜,一個服務的故障可能引發(fā)連鎖反應,導致整個系統(tǒng)雪崩。Sentinel 作為阿里巴巴開源的流量控制框架,能從流量控制、熔斷降級等維度保護服務穩(wěn)定性。本文將從實戰(zhàn)角度,完整講解 Sentinel 的核心概念、使用方式及各類規(guī)則配置。
一、Sentinel 核心概念
1.1 什么是 Sentinel
Sentinel(分布式系統(tǒng)的流量防衛(wèi)兵)以流量為切入點,提供流量控制、熔斷降級、系統(tǒng)負載保護等能力,保障微服務高可用。
1.2 核心概念
- 資源:Sentinel 要保護的對象,可是一個接口、方法、服務等。
- 規(guī)則:定義保護資源的策略,包括流量控制、熔斷降級、熱點參數(shù)、系統(tǒng)規(guī)則、授權規(guī)則等。
- 核心功能:
- 流量控制:限制接口 QPS / 線程數(shù),避免服務被壓垮。
- 熔斷降級:當下游服務異常時,暫時切斷調(diào)用,防止級聯(lián)故障。
二、環(huán)境準備
2.1 搭建基礎微服務
2.1.1 服務提供者(sentinel-provider)
application.yml
server:
port: 9090
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.209.129:8848
application:
name: sentinel-provider核心服務類
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Integer id) {
// 模擬網(wǎng)絡延時
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new User(id,"王糞堆-provider",18);
}
}2.1.2 Feign 接口(sentinel_feign)
@FeignClient("sentinel-provider")
public interface UserFeign {
@RequestMapping(value = "/provider/getUserById/{id}")
public User getUserById(@PathVariable Integer id);
}
2.1.3 服務消費者(sentinel_consumer)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_parent</artifactId>
<groupId>com.hg</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel_consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.hg</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--feign接口-->
<dependency>
<groupId>com.hg</groupId>
<artifactId>sentinel_feign</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--Sentinel核心依賴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
</project>application.yml
server:
port: 8080
tomcat:
max-threads: 10 # 降低tomcat并發(fā),便于測試雪崩
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.209.129:8848
sentinel:
transport:
dashboard: 127.0.0.1:8080 # Sentinel控制臺地址
feign:
client:
config:
default:
connectionTimeout: 5000
readTimeout: 5000
sentinel:
enabled: true # 開啟Feign整合Sentinel三、Sentinel 快速入門
3.1 方式 1:硬編碼(拋異常方式)
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@RequestMapping(value = "/hello")
public String hello() {
Entry entry = null;
try {
// 定義資源
entry = SphU.entry("/consumer/hello");
return "Hello Sentinel!??!";
} catch (BlockException e) {
// 限流兜底邏輯
return "接口被限流了, exception: " + e;
}finally {
if (entry != null) {
entry.exit();
}
}
}
// 初始化限流規(guī)則
@PostConstruct
public void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule1 = new FlowRule();
rule1.setResource("/consumer/hello"); // 資源名
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); // 按QPS限流
rule1.setCount(2); // QPS閾值2
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
}3.2 方式 2:注解方式(推薦)
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
// 開啟Sentinel注解支持
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
return new SentinelResourceAspect();
}
@RequestMapping(value = "/hello2")
@SentinelResource(value="/consumer/hello2",blockHandler = "blockHandlerMethod")
public String hello2() {
return "Hello Sentinel2?。?!";
}
// 限流兜底方法
public String blockHandlerMethod(BlockException e){
return "接口被限流了, exception: " + e;
}
@PostConstruct
public void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule1 = new FlowRule();
rule1.setResource("/consumer/hello2");
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setCount(2);
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
}3.3 Sentinel 控制臺使用
3.3.1 啟動控制臺
# 下載地址:https://github.com/alibaba/Sentinel/releases java -jar sentinel-dashboard-1.8.1.jar
訪問 http://localhost:8080,默認賬號 / 密碼:sentinel/sentinel。
3.3.2 接入控制臺
消費者配置文件中添加:
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080訪問任意接口(如 http://127.0.0.1:8080/consumer/hello3),控制臺即可識別服務。
四、Sentinel 核心規(guī)則配置
4.1 流量控制規(guī)則
流量控制是 Sentinel 最核心的功能,通過限制 QPS / 線程數(shù),防止服務被壓垮。
4.1.1 核心配置項說明
| 配置項 | 說明 |
|---|---|
| 資源名 | 唯一標識,默認請求路徑 |
| 針對來源 | 限制調(diào)用方(默認 default,不區(qū)分來源) |
| 閾值類型 | QPS(每秒請求數(shù))/ 線程數(shù) |
| 流控模式 | 直接(限流當前接口)/ 關聯(lián)(關聯(lián)接口閾值觸發(fā)限流)/ 鏈路(指定入口限流) |
| 流控效果 | 快速失敗 / Warm Up(預熱)/ 排隊等待 |
4.1.2 典型場景配置
(1)QPS 限流
- 規(guī)則配置:資源名
/consumer/getUserById/{id},閾值類型 QPS,單機閾值 2; - 效果:接口 QPS 超過 2 時,直接觸發(fā)限流。
(2)Warm Up(預熱限流)
- 適用場景:流量突增(如秒殺),避免瞬間打滿服務;
- 規(guī)則配置:閾值類型 QPS,單機閾值 6,預熱時長 5 秒;
- 效果:QPS 從 2(6/3)開始,5 秒后升至 6,平滑提升流量處理能力。
(3)排隊等待
- 適用場景:需要勻速處理請求(如削峰填谷);
- 規(guī)則配置:閾值類型 QPS,單機閾值 1,排隊超時時間 10ms;
- 效果:請求勻速通過,超時未處理的請求直接丟棄。
4.2 熱點參數(shù)限流
對接口參數(shù)做精細化限流,支持參數(shù)例外項(如特定 ID 放寬閾值)。
@RequestMapping(value = "/getUserById/{id}")
@SentinelResource(value = "getUserById", blockHandler = "blockHandlerMethod")
public User getUserById(@PathVariable Integer id) {
return userFeign.getUserById(id);
}
// 熱點參數(shù)限流兜底方法
public User blockHandlerMethod(Integer id, BlockException e) {
return new User(id, "熱點參數(shù)限流觸發(fā)", 0);
}- 規(guī)則配置:資源名
getUserById,參數(shù)索引 0(第一個參數(shù)),單機閾值 2; - 例外項配置:參數(shù)值 2,閾值 3(ID=2 時 QPS 閾值提升至 3)。
4.3 熔斷降級規(guī)則
當接口響應慢 / 異常比例高時,暫時切斷調(diào)用,避免級聯(lián)故障。
4.3.1 三種熔斷策略
| 策略 | 觸發(fā)條件 |
|---|---|
| 慢調(diào)用比例 | 慢調(diào)用(RT 超過閾值)占比超過設定值,且請求數(shù)≥最小請求數(shù) |
| 異常比例 | 異常請求占比超過設定值,且請求數(shù)≥最小請求數(shù) |
| 異常數(shù) | 異常請求數(shù)超過設定值,且請求數(shù)≥最小請求數(shù) |
4.3.2 配置示例(慢調(diào)用比例)
- 規(guī)則配置:資源名
/consumer/getUserById/{id},最大 RT 200ms,比例閾值 0.5,熔斷時長 5s,最小請求數(shù) 5; - 效果:5 個請求中若 50% 以上 RT 超過 200ms,觸發(fā)熔斷,5 秒內(nèi)拒絕所有請求。
4.4 授權規(guī)則
基于請求來源做黑白名單控制,適合接口訪問權限管控。
4.4.1 實現(xiàn)來源解析
@Component
public class RequestOriginParserDefinition implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
// 從請求參數(shù)獲取來源標識(可替換為請求頭、Session等)
return request.getParameter("origin");
}
}4.4.2 規(guī)則配置
- 黑名單:資源名
/consumer/getUserById/{id},黑名單值app1; - 效果:來源為
app1的請求直接被拒絕。
4.5 系統(tǒng)規(guī)則
針對整個應用的全局規(guī)則(粒度粗,慎用),支持:
- LOAD(Linux 系統(tǒng)負載);
- RT(所有請求平均響應時間);
- 線程數(shù)(所有請求總線程數(shù));
- 入口 QPS(所有接口總 QPS);
- CPU 使用率。
五、Sentinel 高級特性
5.1 自定義兜底邏輯(blockHandler)
5.1.1 同級別兜底(當前類)
@SentinelResource(value = "getUserById", blockHandler = "blockHandlerMethod")
public User getUserById(@PathVariable Integer id) {
return userFeign.getUserById(id);
}
// 兜底方法(參數(shù)與原方法一致,最后加BlockException)
public User blockHandlerMethod(Integer id, BlockException e) {
return new User(0, "接口被流控/熔斷:"+e, 0);
}5.1.2 外置兜底類(解耦)
// 外置兜底類(方法必須static)
public class BlockHandlerClass {
public static User blockHandlerMethod(Integer id, BlockException e) {
return new User(0, "外置兜底:"+e, 0);
}
}
// 使用外置兜底類
@SentinelResource(value = "getUserById",
blockHandler = "blockHandlerMethod",
blockHandlerClass = BlockHandlerClass.class)
public User getUserById(@PathVariable Integer id) {
return userFeign.getUserById(id);
}5.2 全局異常處理
統(tǒng)一處理 Sentinel 各類異常,返回標準化響應。
@Component
public class GlobalBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setContentType("application/json;charset=utf-8");
Result data = null;
if (e instanceof FlowException) {
data = new Result(-1, "限流異常");
} else if (e instanceof DegradeException) {
data = new Result(-2, "降級異常");
} else if (e instanceof ParamFlowException) {
data = new Result(-3, "參數(shù)限流異常");
} else if (e instanceof AuthorityException) {
data = new Result(-4, "授權異常");
} else if (e instanceof SystemBlockException) {
data = new Result(-5, "系統(tǒng)負載異常");
}
response.getWriter().write(JSON.toJSONString(data));
}
}
// 統(tǒng)一返回體
class Result {
private int status;
private String msg;
private Object data;
// 省略getter/setter/構造器
}5.3 Sentinel 整合 Feign
實現(xiàn) Feign 遠程調(diào)用的熔斷降級,避免下游服務異常影響上游。
5.3.1 實現(xiàn) FallbackFactory
@Component
public class UserFeignFallback implements FallbackFactory<UserFeign> {
@Override
public UserFeign create(Throwable t) {
return new UserFeign() {
@Override
public User getUserById(Integer id) {
return new User(id, "Feign調(diào)用失敗:"+t, 0);
}
};
}
}5.3.2 配置 Feign 接口
@FeignClient(value = "sentinel-provider", fallbackFactory = UserFeignFallback.class)
public interface UserFeign {
@RequestMapping(value = "/provider/getUserById/{id}")
User getUserById(@PathVariable Integer id);
}
六、總結
Sentinel 憑借輕量、易用、靈活的特性,成為 SpringCloud 微服務架構中服務保護的首選方案。核心要點總結:
- 資源定義:通過硬編碼 / 注解 / 自動適配(SpringMVC/Feign)定義受保護資源;
- 規(guī)則配置:控制臺 / 代碼配置流量控制、熔斷降級等規(guī)則,按需選擇粒度;
- 兜底邏輯:通過 blockHandler / 全局異常 / FallbackFactory 處理限流 / 熔斷場景;
- 核心價值:從流量入口到服務調(diào)用全鏈路保護,防止雪崩效應,保障微服務高可用。
建議結合 JMeter 壓測工具驗證各類規(guī)則效果,加深對 Sentinel 流量控制、熔斷降級的理解,根據(jù)業(yè)務場景靈活配置規(guī)則,平衡系統(tǒng)穩(wěn)定性和可用性。
到此這篇關于SpringCloud Alibaba Sentinel 從入門到精通的文章就介紹到這了,更多相關SpringCloud Alibaba Sentinel 使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java中JUC包(java.util.concurrent)下的常用子類
相信大家已經(jīng)對并發(fā)機制中出現(xiàn)的很多的常見知識點進行了總結,下面這篇文章主要給大家介紹了關于Java中JUC包(java.util.concurrent)下的常用子類的相關資料,文中通過圖文以及示例代碼介紹的非常詳細,需要的朋友可以參考下2022-12-12
Java報錯Non-terminating?decimal?expansion解決分析
這篇文章主要為大家介紹了Java報錯Non-terminating?decimal?expansion解決方案及原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09

