系统规则(systemrule)是sentinel的全局自适应保护机制,非传统限流,而是依据cpu使用率、load、平均rt、入口qps、并发线程数等指标动态降低入口流量通过率,实现系统稳定与吞吐量平衡。

系统规则(SystemRule)不是“限流”,而是负载自适应保护
很多人一看到 SystemRule 就下意识当成“系统级限流”,其实它不拦请求,也不看 QPS 或线程数,而是盯着机器真实负载:CPU 使用率、Load、平均 RT、入口 QPS、并发线程数。只要其中任一指标超过阈值,Sentinel 就会**自动降低入口流量通过率**,让系统回到安全水位——这是一种被动但更贴近物理现实的保护方式。
它和 DegradeRule(熔断降级)不同:后者基于单个资源的异常或慢调用做状态切换;前者是全局兜底策略,无需指定资源名,作用于整个应用入口链路。
-
SystemRule的生效前提是应用已接入 Sentinel 客户端,并且监控数据能正常上报(默认每 10 秒上报一次) - CPU 和 Load 指标在 Windows 下不可用,仅 Linux/macOS 生效;RT 和并发线程数则全平台可用
- 多个系统规则同时存在时,**只要任意一条触发,就会开始自适应降载**,不是“与”关系而是“或”关系
- 规则中
highestSystemLoad对应 Linux 的 load average(1 分钟均值),建议设为 CPU 核数 × 0.9 左右,避免过早触发
配置 system-rule 的三种方式及关键区别
系统规则支持动态推送,但配置入口不同,行为也不同:
- 控制台手动添加:路径是「系统管理 → 系统规则」,填完保存即刻生效,但**重启后丢失**,仅适合测试
- Nacos 持久化 push 模式:需引入
sentinel-datasource-nacos,并在application.yml中配置datasource.system.nacos.data-id,dataId 内容必须是合法 JSON 数组,例如:[{"highestSystemLoad":3.5,"avgRt":200,"maxThread":100,"qps":1000}] - 代码硬编码(不推荐):
SystemRuleManager.loadRules(Arrays.asList(rule)),仅用于单元测试或极简场景,无法热更新
注意:SystemRule 不支持「关联资源」「链路限流」等高级字段,所有字段都是全局维度;若同时配置了 FlowRule 和 SystemRule,系统规则优先级更高,可能让流控规则“看起来没生效”。
@SentinelResource 注解对 SystemRule 无效
这是最容易踩的坑:@SentinelResource 只影响资源粒度的 FlowRule、DegradeRule、AuthorityRule,而 SystemRule 是拦截在所有埋点之前的一层网关级保护——它不管你有没有加注解、有没有 SphU.entry(),只要请求进入 WebMvc 或 WebFlux 入口,就参与统计和干预。
- 即使某个 Controller 方法没加
@SentinelResource,只要该服务整体 CPU 超标,SystemRule仍会限制其总入口 QPS - 如果你发现加了系统规则但压测时没触发,先检查
dashboard页面右上角的「实时监控 → 系统」Tab 里指标是否真的超标(尤其是 Load 值是否被正确采集) - 本地开发时 Docker 容器内 CPU 限制可能导致 Load 计算失真,建议在真实 Linux 服务器或 K8s 环境验证
如何验证 SystemRule 是否真正起作用
不能只看控制台规则列表是否显示,要观察实际行为变化:
- 用
curl -s http://localhost:8080/actuator/sentinel | jq '.systemStatus'查看当前系统指标快照,确认load、cpuUsage、rt是否接近你设的阈值 - 模拟高负载:运行
stress-ng --cpu 4 --timeout 60s(Linux),再发起请求,观察响应延迟是否明显上升、部分请求是否返回503 Service Unavailable(默认 block page) - 注意:系统规则不会抛出
BlockException,也不会走blockHandler,它的拒绝是静默的,日志里只有SystemRuleManager的 trace 级别记录
真正难调的是阈值组合:比如低 RT + 高 QPS + 高 CPU,三者互相牵制。建议先固定两个变量,只调一个,再逐步叠加,否则容易误判是规则没生效,其实是指标还没触达临界点。










