Sentinel限流熔断

项目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 限流 / 熔断的资源名(对应 @SentinelResourcevalue -
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
  }
]
相关推荐
talenteddriver2 小时前
mysql: MySQL中between子句和limit子句的区别
前端·javascript·数据库
小徐Chao努力2 小时前
【Langchain4j-Java AI开发】02-模型参数配置与调优
java·开发语言·人工智能
啥都不懂的小小白2 小时前
CyclicBarrier深度解析:Java中的“循环栅栏“同步工具
java·juc·cyclicbarrier
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于uni—app的民宿预订系统为例,包含答辩的问题和答案
java·eclipse
bjxiaxueliang2 小时前
一文详解Cpp多线程编程:从传统pthread到现代thread实践指南
java·开发语言·jvm
机智的人猿泰山2 小时前
spring boot 运行测试类时:Error creating bean with name ‘serverEndpointExporter‘ 问题
java·spring boot·后端
东东的脑洞2 小时前
【面试突击】Redis 哨兵(Sentinel)完全指南:从原理到实战
redis·面试·sentinel
A24207349302 小时前
深入浅出理解AJAX:核心原理与POST/GET区别详解
前端·ajax·okhttp
爬山算法2 小时前
Hibernate(3)Hibernate的优点是什么?
java·后端·hibernate