高并发场景下服务被流量打垮,根因通常不是单点故障,而是缺乏流量控制手段。限流保护系统不被超出容量的请求压垮,熔断保护下游依赖不可用时不让故障蔓延,降级保证核心链路在异常时仍能返回结果。三者合起来是服务治理里最基础的流量防护组合。Sentinel是阿里巴巴开源的流量防护组件,提供实时监控控制台,支持QPS限流、并发线程数限流、熔断降级和系统保护规则,对Spring Cloud、Dubbo、gRPC都有现成适配。本文给出规则配置和落地代码。
限流算法与Sentinel的QPS限流规则
限流算法有计数器、滑动窗口、漏桶、令牌桶几种,Sentinel默认使用滑动窗口计数器,支持秒级QPS统计和并发线程数统计。核心概念是资源(Resource)和规则(Rule),资源通常是方法名或URL,规则定义该资源允许的流量上限。配置规则有两种方式:代码里写@SentinelResource注解,或者直接在控制台配置。
// Spring Boot 集成 Sentinel
// pom.xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2023.0.1.0</version>
</dependency>
// 控制台配置(dashboard)
# application.yml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel控制台地址
eager: true # 启动即注册资源
@RestController
public class OrderController {
@SentinelResource(
value = "create-order",
blockHandler = "createOrderBlock",
fallback = "createOrderFallback"
)
@PostMapping("/api/orders")
public Result createOrder(@RequestBody OrderRequest req) {
return orderService.create(req);
}
// 限流触发时的兜底方法
public Result createOrderBlock(OrderRequest req, BlockException ex) {
return Result.error(429, "请求过于频繁,请稍后重试");
}
// 业务异常时的降级方法
public Result createOrderFallback(OrderRequest req, Throwable t) {
return Result.error(503, "下单服务暂时不可用");
}
}
QPS限流规则通过控制台配置:资源名create-order、阈值100、统计维度QPS。热点参数限流还能针对商品ID、用户ID这类热点参数做细粒度控制,比如秒杀场景同一个商品ID的并发不能超过50,其他商品不受限。
熔断降级:慢调用比例与异常比例规则
熔断的核心是”失败快速失败”,避免下游服务不可用时上游继续把请求打进去。Sentinel支持三种熔断策略:慢调用比例、异常比例、异常数。熔断器状态机:关闭-打开-半开,打开状态下请求直接走降级逻辑,经过静默时间后进入半开状态探测下游是否恢复。
// 熔断规则配置(代码方式,也可控制台配置)
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("create-order");
// 慢调用比例熔断:超过200ms算慢调用,比例达到30%触发熔断
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setCount(200); // 慢调用判定阈值200ms
rule.setTimeWindow(10); // 熔断窗口10秒
rule.setSlowRatioThreshold(0.3); // 慢调用比例30%
rules.add(rule);
DegradeRuleManager.loadRules(rules);
熔断降级和限流的区别要分清:限流是主动保护自己,超过容量就拒绝;熔断是保护下游,发现下游异常主动切走流量。实践中两者的阈值要根据压测数据定,先把正常峰值流量的1.5倍设为限流上限,再按下游服务可用性设熔断阈值,运行一段时间后用真实监控数据修正。
分布式限流与集群规则
单机限流只保护单实例,多实例部署时集群总流量可能超限。Sentinel支持集群限流:一台token-server(令牌服务器)集中统计,其他实例作为token-client请求配额。集群限流引入额外依赖,需要权衡:单机限流足够时不要上集群模式,避免token-server成为新的单点。
// 集群限流配置要点
// 1. 指定token-server
SentinelClusterClientConfig config = new SentinelClusterClientConfig();
config.setServerHost("10.0.0.10");
config.setServerPort(11110);
// 2. 开启集群限流开关
ClusterFlowRule rule = new ClusterFlowRule();
rule.setResourceName("create-order");
rule.setClusterMode(true);
rule.setCount(500); // 集群总QPS上限
rule.setClusterConfig(new ClusterFlowConfig());
与集群限流相比,更常用的是本地限流+容量规划:每台实例上限 = 集群总容量/实例数再打9折,用负载均衡保证流量均匀。这种方案没有额外组件,容量估算准确时效果和集群限流相当,故障面也更小。
热点参数限流与系统自适应保护
热点参数限流针对参数维度:比如同一个用户的调用频率限制,或同一个商品ID的访问频率限制。参数限流支持设定兜底阈值和精确参数阈值,参数未命中精确配置时走兜底值。
@Sentinel
public Product getProduct(@SentinelParam(order = 0, paramKey = "productId") Long productId) {
return productService.get(productId);
}
// 控制台配置热点规则:productId参数的QPS上限为1000,热点参数ID 888888的QPS上限为50
// 兜底值:QPS 1000;热点值:productId=888888 -> 50
系统自适应保护(SystemRule)是最后一道防线:当系统负载(Load1)超过阈值、CPU使用率超过配置或并发线程数超限时,Sentinel自动拒绝新请求,防止整个系统被拖垮。阈值一般设为CPU核数-1,或压测时系统维持稳定响应的最大负载值。
降级策略设计:多级降级与兜底数据
降级不只是返回报错,更合理的做法是提供降级数据:读到主数据源失败时返回缓存副本;缓存也没有时返回上一次成功的结果;都没有时返回静态兜底文案。降级数据质量逐级递减,但保证接口始终有响应。
@Sentinel(value = "get-product", fallback = "getProductFallback")
public ProductVO getProduct(Long id) {
// 主路径:查DB,失败抛异常
return productMapper.selectById(id);
}
public ProductVO getProductFallback(Long id, Throwable t) {
// 第一级降级:查Redis缓存
ProductVO cached = productCache.get(id);
if (cached != null) return cached;
// 第二级降级:本地上一次结果
ProductVO last = productLocalCache.get(id);
if (last != null) return last;
// 最终兜底
return ProductVO.empty(id);
}
降级路径上要埋监控点:降级次数、降级原因分布、降级数据新鲜度。降级不是隐身模式,降级量占比持续偏高说明主链路有问题,需要及时暴露给值班团队。Sentinel控制台自带资源监控面板,把blocked事件和降级事件接进告警系统,限流熔断的效果才能真正闭环。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/gao-bing-fa-xian-liu-rong-duan-shi-zhan-sentinel-gui-ze-pei/