Sentinel服务治理:服务降级、熔断与线程隔离
文章目录
- 前言
- 1. 服务降级
- 1.1 降级概念
- 1.2 Sentinel降级规则
- 慢调用比例策略
- 异常比例策略
- 异常数策略
- 1.3 配置示例
- 2. 服务熔断
- 2.1 熔断机制原理
- 2.2 Sentinel熔断规则
- 慢调用比例策略
- 异常比例策略
- 异常数策略
- 2.3 熔断器状态机
- 2.4 熔断器工作流程
- 3. 线程隔离(Thread Isolation)
- 3.1 隔离目的
- 3.2 两种隔离方式
- 线程池隔离
- 信号量隔离
- 4. 熔断与降级的区别
- 5. 消息系统中的可靠性保障
- 5.1 避免消息重复处理
- 总结
前言
在微服务架构中,服务间的调用链路复杂,任何一个服务的故障都可能引发雪崩效应。Sentinel作为阿里巴巴开源的分布式系统的流量防护组件,通过服务降级、服务熔断和线程隔离等机制,为微服务提供了稳定性保障。
1. 服务降级
1.1 降级概念
服务降级是指在系统压力过大或部分服务不可用时,暂时关闭或简化非核心功能,优先保障核心业务的可用性。
常见降级策略:
- 返回兜底数据:商品详情页无法加载评论,显示"暂无评论"
- 关闭非核心功能:关闭推荐、日志、统计功能
- 限流 + 降级:拒绝部分请求,返回"系统繁忙"
1.2 Sentinel降级规则
Sentinel支持三种降级策略:
慢调用比例策略
当资源的平均响应时间超过阈值(以ms为单位)且在统计窗口内慢调用比例大于设定的比例阈值,则在接下来的熔断时长内请求会自动被熔断。
异常比例策略
当资源的每秒异常总数占通过量的比值超过阈值时,资源进入降级状态。
异常数策略
当资源近1分钟的异常数目超过阈值时会进行熔断。
1.3 配置示例
@SentinelResource(value = "getUserInfo", fallback = "getUserInfoFallback")
public User getUserInfo(Long userId) {return userService.findById(userId);
}// 降级方法
public User getUserInfoFallback(Long userId, Throwable ex) {return new User(userId, "默认用户", "系统繁忙,请稍后再试");
}
2. 服务熔断
2.1 熔断机制原理
服务熔断是一种保护机制。当某个下游服务频繁失败(如超时、异常率高),调用方会暂时切断对该服务的调用,直接返回一个预设的错误响应或兜底逻辑,避免资源被持续占用。
2.2 Sentinel熔断规则
Sentinel支持三种熔断策略:
慢调用比例策略
当资源的平均响应时间超过阈值(以ms为单位)且在统计窗口内慢调用比例大于设定的比例阈值,则在接下来的熔断时长内请求会自动被熔断。
异常比例策略
当资源的每秒异常总数占通过量的比值超过阈值时,资源进入降级状态。
异常数策略
当资源近1分钟的异常数目超过阈值时会进行熔断。
2.3 熔断器状态机
Sentinel的熔断器有三种状态:
- 关闭(Closed):正常调用服务,统计失败率
- 打开(Open):达到失败阈值,触发熔断。所有请求直接失败,不调用远程服务,持续一段时间(如5秒)
- 半开(Half-Open):时间到期后,进入半开状态。允许部分请求尝试调用服务。如果成功,恢复为"关闭";如果仍失败,回到"打开"
2.4 熔断器工作流程
- 正常状态:服务正常调用,熔断器为关闭状态
- 异常检测:统计失败率、响应时间等指标
- 触发熔断:达到阈值时,熔断器打开,直接返回失败
- 尝试恢复:等待时间后进入半开状态,允许少量请求通过
- 状态决策:根据测试请求结果决定关闭或重新打开熔断器
3. 线程隔离(Thread Isolation)
3.1 隔离目的
线程隔离通过为不同的资源分配独立的线程池,防止某个服务的线程耗尽影响到其他服务,实现故障隔离。
3.2 两种隔离方式
线程池隔离
为不同的服务调用分配独立的线程池,彻底隔离资源。
@Bean("userServiceExecutor")
public ThreadPoolExecutor userServiceExecutor() {return new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(100));
}
信号量隔离
通过信号量控制并发数,适用于高频调用场景,开销较小。
// 限制并发数为10
private final Semaphore semaphore = new Semaphore(10);public String processLimitedResource(String input) {try {semaphore.acquire();return doProcess(input);} finally {semaphore.release();}
}
4. 熔断与降级的区别
在微服务架构中,熔断和降级是两个重要但不同的概念:
-
熔断 → 是一种技术手段,用于自动应对服务异常
- 目标:防止故障扩散,保护系统资源
- 触发:自动检测服务异常率、响应时间等指标
- 恢复:通过半开状态自动尝试恢复
-
降级 → 是一种业务策略,目标是保障系统可用性
- 目标:在资源有限时保证核心功能可用
- 触发:可以手动或自动触发
- 恢复:通常需要人工干预或业务流程恢复
5. 消息系统中的可靠性保障
5.1 避免消息重复处理
在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,可以将inner-msg-id存入缓存(如Redis),设置TTL,作为去重的依据,避免重复的消息进入队列。
在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID等)作为去重的依据,避免同一条消息被重复消费。
// 消费端去重示例
public void processPayment(PaymentMessage message) {String bizId = message.getPaymentId();if (redis.hasKey("processed:pay:" + bizId)) {return; // 已处理}// 执行支付回调逻辑paymentService.processCallback(message);// 标记已处理redis.setex("processed:pay:" + bizId, 24*3600, "1");
}
总结
Sentinel通过多层次的流量防护机制,为微服务架构提供了全面的稳定性保障:
- 流量控制:通过QPS限流、并发数控制等方式防止系统过载
- 服务降级:通过规则自动检测异常并切断故障服务,执行兜底逻辑
- 热点参数限流:针对热点数据进行特殊保护
- 线程隔离:通过资源隔离,避免服务间相互影响
在实际应用中,需要根据具体业务场景合理配置各种规则,建立完善的监控体系,并制定相应的运维流程。只有将这些机制有机结合,才能构建出真正高可用的微服务系统。