项目gitee链接
1.Sentinel控制台配置
官网下载sentinel-dashboard-1.8.8.jar
bat快速启动
cpp
@echo off
rem 快速启动 Sentinel 控制台(Windows)
rem 如已下载 JAR,请设置 JAR_PATH,或自动探测默认路径/版本
set DASHBOARD_PORT=8858
set DASHBOARD_USER=sentinel
set DASHBOARD_PASS=sentinel
rem 优先使用用户已设置的 JAR_PATH
if not defined JAR_PATH (
rem 首选用户给出的目录与版本
if exist "D:\IDEA\sentinel\sentinel-dashboard-1.8.8.jar" (
set JAR_PATH=D:\IDEA\sentinel\sentinel-dashboard-1.8.8.jar
) else if exist "D:\IDEA\sentinel\sentinel-dashboard-1.8.6.jar" (
set JAR_PATH=D:\IDEA\sentinel\sentinel-dashboard-1.8.6.jar
) else if exist "sentinel-dashboard-1.8.8.jar" (
set JAR_PATH=sentinel-dashboard-1.8.8.jar
) else if exist "sentinel-dashboard-1.8.6.jar" (
set JAR_PATH=sentinel-dashboard-1.8.6.jar
) else (
set JAR_PATH=sentinel-dashboard-1.8.8.jar
)
)
if not exist "%JAR_PATH%" (
echo 未找到 %JAR_PATH%,请先下载 https://github.com/alibaba/Sentinel/releases
echo 或手动设置 JAR_PATH=完整jar路径 后再运行本脚本
pause
exit /b 1
)
echo Using JAR: %JAR_PATH%
echo Starting Sentinel Dashboard on port %DASHBOARD_PORT% ...
echo username: %DASHBOARD_USER% password: %DASHBOARD_PASS%
java -Dserver.port=%DASHBOARD_PORT% ^
-Dsentinel.dashboard.auth.username=%DASHBOARD_USER% ^
-Dsentinel.dashboard.auth.password=%DASHBOARD_PASS% ^
-jar "%JAR_PATH%"
properties配置
cpp
# 1. 指定 Sentinel 控制台的地址(你的控制台运行在localhost:8858)
spring.cloud.sentinel.transport.dashboard=localhost:8858
# 2. 客户端与控制台通信的端口(默认8719,若被占用可修改,如8720)
spring.cloud.sentinel.transport.port=8719
# 3. (可选)关闭控制台懒加载(启动应用即连接控制台,默认是触发请求后才连接)
spring.cloud.sentinel.eager=true
logging.level.com.alibaba.csp.sentinel=DEBUG
logging.level.com.alibaba.csp.sentinel.transport=INFO
# 打印请求映射日志
logging.level.org.springframework.web.servlet: debug
# ========== Sentinel 本地文件持久化配置 ==========
# 1. 限流规则文件数据源
spring.cloud.sentinel.datasource.ds1.file.file=classpath:sentinel/flow-rules.json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
# 2. 熔断规则文件数据源
spring.cloud.sentinel.datasource.ds2.file.file=classpath:sentinel/degrade-rules.json
spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade
2.本地化配置sentinel规则
规则文件字段说明
| 字段 | 含义 | 可选值 |
|---|---|---|
resource |
限流 / 熔断的资源名(对应 @SentinelResource 的 value) |
- |
limitApp |
流控应用 | default(所有应用)、具体应用名 |
grade(限流) |
阈值类型 | 1(QPS)、0(线程数) |
grade(熔断) |
熔断策略 | 0(异常比例)、1(异常数)、2(慢调用比例) |
count(限流) |
QPS / 线程数阈值 | 正整数 |
count(熔断) |
异常比例 / 异常数 / 慢调用比例阈值 | 异常比例(0-1)、异常数(正整数)、慢调用比例(0-1) |
timeWindow |
熔断时长(秒) | 正整数 |
minRequestAmount |
熔断最小请求数 | 正整数(避免少量请求触发熔断) |
限流json
bash
[
{
"resource": "sentinel-test-noParam", // 无参接口资源名
"limitApp": "default", // 流控应用(default表示所有应用)
"grade": 1, // 阈值类型:1=QPS限流,0=线程数限流
"count": 2, // QPS阈值:每秒允许2次请求
"strategy": 0, // 流控模式:0=直接限流,1=关联,2=链路
"controlBehavior": 0, // 流控效果:0=快速失败,1=Warm Up,2=排队等待
"clusterMode": false // 是否集群限流:false=单机
}
]
熔断json
bash
[
{
"resource": "sentinel-test-exception", // 异常测试接口资源名
"grade": 0, // 熔断策略:0=异常比例,1=异常数,2=慢调用比例
"count": 0.5, // 阈值:异常比例超过50%触发熔断
"timeWindow": 5, // 熔断时长:5秒(熔断后5秒内请求直接降级)
"minRequestAmount": 5, // 最小请求数:至少5次请求后才计算异常比例
"statIntervalMs": 1000, // 统计时间窗口:1000毫秒(1秒)
"slowRatioThreshold": 0.1 // 慢调用比例阈值(仅慢调用策略生效)
}
]
3.nacos配置sentinel规则
到时候再补充,sentinel规则持久化
4.@SentinelResource
cpp
@SentinelResource(
value = "sentinel-test-noParam", //值名称
blockHandlerClass = CommonSentinelFallback.class, //限流方法所在类
blockHandler = "commonBlockHandlerNoParam", //限流方法
fallbackClass = CommonSentinelFallback.class, //熔断异常方法所在类
fallback = "commonFallbackNoParam" // 熔断异常方法
)
自定义异常和限流方法
bash
//缓存模块的限流降级方法
public class CacheSentinelFallbacks {
// 适配 cache-clearAll 、cache-clearCurrent 接口(返回 BaseResponse<Boolean>)
public static BaseResponse<Object> handleBlockCache(BlockException e) {
return ResultUtils.error(429, "缓存清理接口触发限流,请稍后再试!");
}
// 适配 cache-clearAll 、cache-clearCurrent 接口(返回 BaseResponse<Boolean>)
public static BaseResponse<Object> handleFallbackCache(Throwable e) {
return ResultUtils.error(500, "缓存清理接口执行异常:" + e.getMessage());
}
}
5.@SentinelController
定义注解
bash
/**
* 自定义Sentinel控制器注解:标注在控制器类上,为所有方法统一配置限流/熔断
*/
@Target({ElementType.TYPE}) // 仅作用于类
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SentinelController {
/**
* 统一的资源名前缀(最终资源名 = 前缀 + 方法名)
*/
String resourcePrefix() default "sentinel-controller-";
/**
* 是否开启限流
*/
boolean enableFlow() default true;
/**
* 是否开启异常降级
*/
boolean enableFallback() default true;
}
定义切点,补充限流方法和熔断异常方法
bash
package com.example.origin_project.common.log.aspect;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.origin_project.common.BaseResponse;
import com.example.origin_project.common.ResultUtils;
import com.example.origin_project.common.log.annotation.SentinelController;
import com.example.origin_project.sentinel.CommonSentinelFallback;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* Sentinel 控制器统一切面:为标注@SentinelController的控制器批量配置限流/熔断
*/
@Aspect
@Component
public class SentinelControllerAspect {
/**
* 切点:匹配所有标注了@SentinelController的控制器类中的方法
*/
@Pointcut("@within(com.example.origin_project.common.log.annotation.SentinelController)")
public void sentinelControllerPointcut() {
}
/**
* 环绕通知:为方法添加Sentinel限流/熔断逻辑
*/
@Around("sentinelControllerPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 1. 获取控制器类的@SentinelController注解配置
Class<?> controllerClass = joinPoint.getTarget().getClass();
SentinelController sentinelController = controllerClass.getAnnotation(SentinelController.class);
if (sentinelController == null) {
return joinPoint.proceed();
}
String controllerName = controllerClass.getSimpleName();
String resourceName = sentinelController.resourcePrefix() + controllerName;
Entry entry = null;
try {
// 3. Sentinel 资源进入(触发限流/熔断规则检查)
entry = SphU.entry(resourceName, EntryType.IN);
// 4. 执行原方法
return joinPoint.proceed();
} catch (BlockException e) {
// 5. 触发限流/熔断:调用统一的blockHandler
return handleBlockException(joinPoint, e);
} catch (Throwable e) {
// 6. 业务异常:调用统一的fallback,并记录异常到Sentinel
Tracer.trace(e); // 必须调用Tracer.trace,否则熔断规则无法检测到异常
return handleFallbackException(joinPoint, e);
} finally {
if (entry != null) {
entry.exit();
}
}
}
/**
* 处理限流/熔断异常(对应blockHandler)
*/
private Object handleBlockException(ProceedingJoinPoint joinPoint, BlockException e) {
// 调用CommonSentinelFallback中的统一限流逻辑,也可根据方法参数动态处理
return CommonSentinelFallback.commonBlockHandler(joinPoint.getArgs(), e);
}
/**
* 处理业务异常(对应fallback)
*/
private Object handleFallbackException(ProceedingJoinPoint joinPoint, Throwable e) {
// 调用CommonSentinelFallback中的统一异常逻辑
return CommonSentinelFallback.commonFallback(joinPoint.getArgs(), e);
}
}
额外配置的公共业务限流和异常方法
bash
/**
* Sentinel 公共降级类:所有控制器共享统一的降级逻辑
*/
public class CommonSentinelFallback {
// ====================== 通用限流/熔断降级方法(blockHandler) ======================
/**
* 通用限流降级:适配返回 BaseResponse<T> 的接口(泛型方法)
*
* @param e Sentinel 限流/熔断异常
* @param <T> 接口返回值的泛型类型
* @return 统一的降级响应
*/
public static <T> BaseResponse<T> commonBlockHandler(BlockException e) {
// 所有接口触发限流时,都返回"业务繁忙"的提示
return ResultUtils.error(429, "当前业务繁忙,请稍后再试common!");
}
/**
* 重载:适配带参数的接口(如 Long id、String username 等)
* Sentinel 要求 blockHandler 方法参数需与原接口一致,因此需重载适配不同参数
*/
public static <T> BaseResponse<T> commonBlockHandler(Long id, BlockException e) {
// return ResultUtils.error(429, "尊敬的用户{id},你好,当前业务繁忙,请稍后再试!");
return ResultUtils.error(429,format("尊敬的用户{id},你好,当前业务繁忙,请稍后再试common!",id));
}
public static <T> BaseResponse<T> commonBlockHandler(Object obj, BlockException e) {
return ResultUtils.error(429, "当前业务繁忙,请稍后再试!common");
}
public static <T> BaseResponse<T> commonBlockHandler(String message,BlockException e) {
return ResultUtils.error(429, "当前业务繁忙,请稍后再试!common:"+message);
}
// ====================== 通用异常降级方法(fallback) ======================
/**
* 通用异常降级:适配返回 BaseResponse<T> 的接口
*
* @param e 业务异常
* @param <T> 接口返回值的泛型类型
* @return 统一的异常响应
*/
public static <T> BaseResponse<T> commonFallback(Throwable e) {
return ResultUtils.error(500, "系统内部异常,请稍后再试common!");
}
/**
* 重载:适配带参数的接口
*/
public static <T> BaseResponse<T> commonFallback(Long id, Throwable e) {
return ResultUtils.error(500, format("尊敬的用户'{id}',你好,系统内部异常,请稍后再试common!",id));
}
public static <T> BaseResponse<T> commonFallback(String message, Throwable e) {
return ResultUtils.error(500, "系统内部异常,请稍后再试common:!"+message);
}
public static <T> BaseResponse<T> commonFallback(Object obj, Throwable e) {
return ResultUtils.error(500, "系统内部异常,请稍后再试!common");
}
}
6.限流规则
java
{
"project": "redisson_demo",
"ruleType": "Sentinel限流规则",
"resource": "sentinel-test-unified",
"ruleDesc": "控制器所有接口共享的统一限流规则",
"paramExplain": {
"resource": {
"required": true,
"value": "sentinel-test-unified",
"desc": "资源名,对应控制器类上@SentinelResource的value属性,所有接口共享该资源"
},
"limitApp": {
"required": false,
"value": "redisson_demo",
"desc": "流控应用,指定仅对redisson_demo应用的调用限流;default表示对所有调用方限流"
},
"grade": {
"required": true,
"value": 1,
"desc": "阈值类型,1=按QPS限流,0=按线程数限流"
},
"count": {
"required": true,
"value": 5,
"desc": "阈值,QPS=5表示每秒允许5次请求;若为线程数则表示最大并发线程数"
},
"strategy": {
"required": false,
"value": 0,
"desc": "流控模式,0=直接限流(针对当前资源),1=关联限流,2=链路限流"
},
"controlBehavior": {
"required": false,
"value": 0,
"desc": "流控效果,0=快速失败(超出阈值直接降级),1=Warm Up(预热模式),2=排队等待"
},
"warmUpPeriodSec": {
"required": false,
"value": 10,
"desc": "预热时间,仅controlBehavior=1时生效,单位秒,10秒内QPS从低到高逐步达到阈值"
},
"maxQueueingTimeMs": {
"required": false,
"value": 500,
"desc": "排队等待超时时间,仅controlBehavior=2时生效,单位毫秒,500ms内排队,超时则降级"
},
"clusterMode": {
"required": false,
"value": false,
"desc": "是否集群限流,false=单机限流,true=集群限流(需配合Sentinel集群服务)"
}
}
}
限流方法本地部署
bash
[
{
"resource": "sentinel-test-unified",
"limitApp": "redisson_demo",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 500,
"clusterMode": false
}
]
7.熔断规则
bash
{
"project": "redisson_demo",
"ruleType": "Sentinel熔断规则",
"resource": "sentinel-test-unified",
"ruleDesc": "控制器所有接口共享的统一熔断规则",
"paramExplain": {
"resource": {
"required": true,
"value": "sentinel-test-unified",
"desc": "资源名,与限流规则一致,针对统一资源触发熔断"
},
"grade": {
"required": true,
"value": 0,
"desc": "熔断策略,0=异常比例,1=异常数,2=慢调用比例"
},
"count": {
"required": true,
"value": 0.5,
"desc": "阈值,异常比例=0.5表示50%的请求异常则触发熔断;异常数则为具体数值;慢调用比例为0-1的小数"
},
"timeWindow": {
"required": true,
"value": 10,
"desc": "熔断时长,单位秒,熔断后10秒内请求直接降级"
},
"minRequestAmount": {
"required": false,
"value": 10,
"desc": "最小请求数,触发熔断的最小请求量(10次),避免少量请求触发熔断"
},
"statIntervalMs": {
"required": false,
"value": 1000,
"desc": "统计时间窗口,单位毫秒,统计1秒内的异常比例/数"
},
"slowRatioThreshold": {
"required": false,
"value": 0.1,
"desc": "慢调用比例阈值,仅grade=2时生效,0.1表示10%的请求为慢调用则触发熔断"
},
"slowCallRtMs": {
"required": false,
"value": 500,
"desc": "慢调用阈值,仅grade=2时生效,单位毫秒,请求耗时超过500ms则视为慢调用"
}
}
}
熔断方法本地部署
bash
[
{
"resource": "sentinel-test-unified",
"grade": 0,
"count": 0.5,
"timeWindow": 10,
"minRequestAmount": 10,
"statIntervalMs": 1000,
"slowRatioThreshold": 0.1,
"slowCallRtMs": 500
}
]