在分布式系统架构演进过程中,服务实例的动态扩缩容已成为常态。某电商大促期间,商品详情页的QPS从日常的2000突然飙升到20000,此时如果没有有效的流量控制机制,系统就会像早高峰没有红绿灯的十字路口——所有请求一拥而上,最终导致整个调用链路雪崩。这正是Sentinel要解决的核心问题。
我亲历过多次线上流量突增引发的故障,最严重的一次因为秒杀活动未做限流,导致订单服务DB连接池耗尽,整个交易链路瘫痪近20分钟。后来引入Sentinel后,通过配置QPS流控规则,即使面对十倍于平时的流量冲击,核心服务也能保持稳定。这种"预防式"的稳定性保障,正是微服务架构不可或缺的基础能力。
Sentinel的流量控制绝非简单的"请求数限制",而是提供多层次的精细控制策略。以电商下单场景为例:
java复制// 针对重要资源创建流控规则
FlowRule rule = new FlowRule("createOrder")
.setCount(100) // 阈值
.setGrade(RuleConstant.FLOW_GRADE_QPS) // QPS模式
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP) // 预热模式
.setWarmUpPeriodSec(10); // 预热时间
这里特别要说明CONTROL_BEHAVIOR_WARM_UP的作用。当系统刚启动时,各种缓存尚未就绪,直接承受高流量极易崩溃。预热模式会让阈值从count/3开始,在10秒内缓慢上升到设定值,就像运动员比赛前需要热身一样。
熔断机制是系统最后的防线。Sentinel采用基于响应时间的熔断策略:
| 统计窗口(ms) | 慢调用比例阈值 | 最小请求数 | 熔断时长(ms) |
|---|---|---|---|
| 10000 | 0.5 | 10 | 5000 |
这个配置表示:当10秒内超过50%的请求响应时间大于阈值(默认1s),且总请求数≥10次时触发熔断。5秒后会进入半开状态试探性放行部分请求。
经验之谈:熔断时长建议设置为平均故障恢复时间的2-3倍。设置过短会导致反复熔断,过长则影响用户体验。
这是Sentinel最具特色的能力。通过实时采集以下指标:
采用PID控制算法动态调整流量。当CPU使用率超过80%时,会自动拒绝部分请求,这与传统静态阈值相比能更精准地保护系统。
在application.yml中需要特别注意的配置项:
yaml复制spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 控制台地址
eager: true # 取消懒加载
filter:
url-patterns: /** # 监控所有端点
常见坑点:
eager: true会导致首次请求无法被监控@SentinelRestTemplate注解sentinel-feign依赖| 方案 | 实时性 | 复杂度 | 适用场景 |
|---|---|---|---|
| 原生Dashboard | 高 | 低 | 开发测试环境 |
| Nacos配置中心 | 中 | 中 | 生产环境动态调整 |
| ZooKeeper | 高 | 高 | 金融级系统 |
| 文件配置 | 低 | 低 | 静态规则 |
我们最终选择Nacos方案,核心代码片段:
java复制@Data
public class FlowRuleWrapper {
private String resource;
private int count;
// 其他字段...
public FlowRule toRule() {
FlowRule rule = new FlowRule();
rule.setResource(this.resource);
rule.setCount(this.count);
return rule;
}
}
通过Nacos配置变更监听,实现规则的热更新。
针对商品查询接口,我们可以对不同商品ID实施差异化限流:
java复制@SentinelResource(value = "getProductInfo", blockHandler = "handleBlock")
public ProductInfo getProductInfo(
@RequestParam("id") Long productId,
@RequestParam("type") String type) {
// 业务逻辑
}
// 热点规则配置
ParamFlowRule rule = new ParamFlowRule("getProductInfo")
.setParamIdx(0) // 对第一个参数限流
.setCount(50); // 全局阈值
当爆款商品(如iPhone新品)的查询QPS超过阈值时,只会限制该商品的查询,不影响其他商品。
结合Spring Cloud Gateway的全局过滤器:
java复制public class SentinelGatewayFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String routeId = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_PREDICATE_MATCHED_PATH_ROUTE_ATTR);
Entry entry = null;
try {
entry = SphU.entry(routeId, EntryType.IN);
return chain.filter(exchange);
} catch (BlockException e) {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
}
}
这种方案比简单的nginx限流更灵活,可以针对不同路由设置不同规则。
推荐使用Prometheus + Grafana的监控组合:
java复制@Bean
public SentinelCollector sentinelCollector() {
return new SentinelCollector() {
@Override
public List<MetricFamilySamples> collect() {
List<MetricFamilySamples> samples = new ArrayList<>();
// 转换Sentinel指标数据
convertQPSMetrics(samples);
convertThreadMetrics(samples);
return samples;
}
};
}
关键监控指标包括:
当出现限流异常时,可以通过以下命令快速定位问题:
bash复制# 查看实时日志
tail -f /logs/app-info.log | grep "Sentinel"
# 典型日志示例
2023-08-20 14:00:00 [Sentinel]|1|createOrder|pass|20|0
2023-08-20 14:00:01 [Sentinel]|1|createOrder|block|0|1
字段说明:时间戳|资源分类|资源名|操作结果|通过数|拒绝数
建议采用规则版本化管理:
code复制/sentinel-rules
├── dev
│ ├── flow-rule.json
│ └── degrade-rule.json
├── test
└── prod
├── flow-rule.json
└── circuit-breaker.json
通过CI/CD流水线实现规则配置的自动化发布,与代码版本严格对应。
使用ChaosBlade工具模拟以下场景:
配合Sentinel看板观察系统反应,验证熔断降级策略的有效性。
在最近一次全链路压测中,我们通过Sentinel的集群流控功能,成功抵御了10万QPS的流量冲击,核心服务SLA保持在99.99%。这充分证明了合理的流量治理方案对系统稳定性的价值。