Sentinel系统保护规则深度解析

以下内容为 Sentinel 的系统保护规则(SystemRule) 实现,它用于从全局系统维度对服务进行自我保护,防止因突发流量或资源耗尽导致系统雪崩。

下面我将结构化、深入浅出地解释其设计思想、核心机制和使用方式。


🧠 一、SystemRule 是什么?

SystemRule(系统规则) 不针对某个具体接口,而是监控整个应用的全局状态,当系统整体负载过高时,自动拒绝部分请求,保护系统不崩溃。

✅ 它监控 5 个关键指标:

指标 含义 单位 默认值(-1 表示关闭)
highestSystemLoad 系统平均负载(Linux load average) double -1(关闭)
highestCpuUsage CPU 使用率 [0, 1] -1(关闭)
qps 全局总 QPS(所有入口流量之和) double -1(关闭)
avgRt 全局平均响应时间 毫秒 -1(关闭)
maxThread 全局最大并发线程数 long -1(关闭)

⚠️ 注意:只对 EntryType.IN(入口流量)生效,出口调用(如 Feign、Dubbo 调用下游)不受限。


🔍 二、核心类解析

1. SystemRule:规则定义类

  • 继承 AbstractRule
  • 包含上述 5 个阈值字段
  • setter 方法中,≤ 0 的值表示"清除该阈值"
  • 支持动态更新(通过 SentinelProperty

2. SystemRuleManager:规则管理器 + 执行引擎

  • 静态单例,全局唯一
  • 提供 loadRules() 加载规则
  • 提供 checkSystem() 方法,在每次请求进入时被调用(由 Sentinel Slot Chain 触发)
  • 内部维护 5 个 volatile 阈值变量,支持多线程安全读取
  • 启动一个 每秒执行一次的定时任务SystemStatusListener),采集系统指标

3. SystemStatusListener:系统指标采集器

  • 实现 Runnable,由 ScheduledExecutorService 每秒调度
  • 通过 JMX(Java Management Extensions) 获取:
    • OperatingSystemMXBean.getSystemLoadAverage() → 系统负载
    • OperatingSystemMXBean.getSystemCpuLoad() → 系统 CPU 使用率
    • getProcessCpuTime() + uptime → 进程 CPU 使用率(更适用于容器环境)
  • 将最新指标存入 volatile 字段,供 checkSystem() 读取

⚙️ 三、checkSystem():核心拦截逻辑

java 复制代码
public static void checkSystem(ResourceWrapper resource, int count) throws BlockException {
    // 1. 只检查入口流量
    if (resource.getEntryType() != EntryType.IN) return;

    // 2. 检查 QPS
    if (Constants.ENTRY_NODE.passQps() + count > qps) 
        throw new SystemBlockException("qps");

    // 3. 检查线程数
    if (Constants.ENTRY_NODE.curThreadNum() > maxThread)
        throw new SystemBlockException("thread");

    // 4. 检查平均 RT
    if (Constants.ENTRY_NODE.avgRt() > maxRt)
        throw new SystemBlockException("rt");

    // 5. 检查系统负载(带 BBR 优化)
    if (load > threshold && !checkBbr(currentThread))
        throw new SystemBlockException("load");

    // 6. 检查 CPU 使用率
    if (cpuUsage > threshold)
        throw new SystemBlockException("cpu");
}

💡 Constants.ENTRY_NODE 是 Sentinel 的根节点 ,统计所有入口流量的聚合指标


🧩 四、关键机制详解

✅ 1. 系统负载(Load)与 BBR 算法

Sentinel 借鉴了 TCP BBR(Bottleneck Bandwidth and RTT) 的思想:

当系统负载高时,不一定立刻熔断,而是判断当前是否处于"危险区"。

checkBbr() 逻辑:
java 复制代码
private static boolean checkBbr(int currentThread) {
    // 计算理论最大并发 = 最大成功QPS × 最小RT / 1000
    long theoreticalMaxConcurrency = maxSuccessQps * minRt / 1000;
    
    // 如果当前线程数 > 理论最大并发,说明已过载 → 拒绝
    return !(currentThread > 1 && currentThread > theoreticalMaxConcurrency);
}

📌 意义 :避免在"管道刚满"时误判为过载。只有当排队严重(线程数远超容量) 时才熔断。


✅ 2. CPU 使用率的双重采集

java 复制代码
double systemCpuUsage = osBean.getSystemCpuLoad();      // 整机 CPU
double processCpuUsage = ...;                           // 当前 JVM 进程 CPU

currentCpuUsage = Math.max(processCpuUsage, systemCpuUsage);

🎯 为什么取 max?

  • 物理机 上,systemCpuLoad 更准
  • Docker/K8s 容器 中,systemCpuLoad 可能不准(看到的是宿主机负载),而 processCpuTime 更可靠
  • 取 max 保证最坏情况被捕捉

✅ 3. 多规则合并策略

当你配置多个 SystemRule 时:

java 复制代码
loadSystemConf(rule) {
    highestSystemLoad = Math.min(highestSystemLoad, rule.getHighestSystemLoad());
    qps = Math.min(qps, rule.getQps());
    // ...
}

📌 取最严格的阈值(最小值)

例如:规则 A 设 QPS=100,规则 B 设 QPS=80 → 实际生效的是 80


🛠️ 五、如何使用?

示例:限制全局 QPS ≤ 100,线程数 ≤ 10,RT ≤ 50ms

java 复制代码
List<SystemRule> rules = new ArrayList<>();

SystemRule rule = new SystemRule();
rule.setQps(100);          // 全局 QPS ≤ 100
rule.setMaxThread(10);     // 并发线程 ≤ 10
rule.setAvgRt(50);         // 平均 RT ≤ 50ms

SystemRuleManager.loadRules(Collections.singletonList(rule));

高级用法:结合 CPU 和 Load(仅 Linux)

java 复制代码
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(5.0);   // load average ≤ 5
rule.setHighestCpuUsage(0.8);     // CPU ≤ 80%
SystemRuleManager.loadRules(...);

⚠️ 注意:highestSystemLoad 在 Windows 上无效(返回 -1)


📊 六、监控与日志

当系统负载超过阈值时,SystemStatusListener 会打印详细日志:

复制代码
[INFO] Load exceeds the threshold: 
load:6.2341; cpuUsage:0.8721; qps:120.5; rt:65.3; thread:15; 
success:110.2; minRt:20.0; maxSuccess:115.0

帮助你快速定位是 CPU、线程、RT 还是 QPS 导致的问题。


🧪 七、性能测试建议

官方注释提到:

"To set the threshold appropriately, performance test may be needed."

✅ 建议步骤:

  1. 压测系统,找到 最大稳定 QPS(maxSuccessQps)
  2. 记录此时的 平均 RT、线程数、CPU、Load
  3. 将阈值设为 稳定值的 70%~80%,留出安全余量

❓常见问题

Q:为什么设置了 QPS=100,但实际通过了 105?

A:Sentinel 注释中提到:

real passed QPS = QPS set + concurrent thread number

因为 QPS 统计有延迟,且允许少量突发(类似令牌桶),这是正常现象。

Q:SystemRule 和 DegradeRule 有什么区别?

对比项 SystemRule DegradeRule
作用范围 全局(整个应用) 单个资源(如 /order)
触发条件 系统级指标(CPU/Load/QPS) 资源级指标(RT/异常)
目的 防系统雪崩 防慢调用/异常扩散

✅ 两者互补:SystemRule 保命,DegradeRule 精细化治理。


✅ 总结

Sentinel 的 SystemRule 是一个"系统级熔断器",它:

  • 🛡️ 从全局视角保护应用,防止资源耗尽
  • 📈 实时采集 CPU、Load、QPS、RT、线程 5 大指标
  • 🧠 引入 BBR 思想,避免误判
  • 🐳 兼容容器环境,精准获取进程 CPU
  • ⚙️ 支持动态配置,无需重启

💡 最佳实践 :在生产环境中,务必配置 SystemRule 作为最后一道防线,配合 DegradeRule 和 FlowRule,构建完整的稳定性体系。

理解这些,你就掌握了 Sentinel 最高层级的自我保护能力

相关推荐
lang201509286 小时前
深入解析Sentinel熔断机制
java·前端·sentinel
lang201509286 小时前
Sentinel熔断降级核心:DegradeSlot解析
sentinel
yfs10241 天前
Sentinel-2哨兵二号卫星农业方向可获取信息
sentinel
GIS工具-gistools20211 天前
用 Sentinel-1 Sentinel-2 结合监测 矿场采掘情况
大数据·sentinel·gis
lang201509281 天前
Sentinel黑白名单授权控制详解
java·算法·sentinel
lang201509281 天前
Sentinel预热限流器深度解析
sentinel
lang201509281 天前
Sentinel熔断降级规则管理详解
sentinel
不会写程序的未来程序员1 天前
Redis 哨兵(Sentinel)原理
数据库·redis·sentinel
lang201509282 天前
Sentinel流控规则检查源码级分析
sentinel