熔断降级的基本原理:
熔断(Circuit Breaker)
1. 当某个服务调用出现大量失败或者响应时间过长时,Sentinel会将该服务调用的断路器打开,进入熔断状态。这时后续对该服务的调用不再执行实际操作,而是立即返回预设的fallback响应,例如错误提示或其他替代数据,以此迅速释放资源,防止服务雪崩效应。
2. 在熔断状态维持一段时间后(冷却期),Sentinel会让断路器进入半开状态尝试进行一次健康检查调用。如果这次调用成功,则认为服务已恢复,断路器关闭,继续正常调用;如果调用仍然失败,则继续保持打开状态,再次进入熔断模式。
熔断(Degradation)
降级主要是指在系统压力较大或者依赖的服务出现不稳定时,暂时降低部分服务的功能级别或者完全关闭部分不重要的服务,保证核心服务的正常运行。Sentinel提供了多种降级策略:
- **基于响应时间降级**:当资源的平均响应时间超过设定的阈值,并且在指定的时间窗口内持续探测到请求响应时间过长,则触发降级。
- **基于异常比率降级**:当资源的异常比例(例如抛出特定异常的请求占比)超过设定阈值时,Sentinel也会启动降级逻辑。
技术实现
令牌桶算法(Token Bucket Algorithm)是一种网络流量整形和速率限制算法。在该算法中,想象有一个固定容量的桶用来存放令牌,系统会以一定的恒定速率往桶中添加令牌。当请求到来时,需要从桶中获取一个令牌来处理这个请求,若桶中有足够的令牌则允许请求通过,若桶为空则拒绝请求。这样可以确保请求的处理速率不会超过令牌添加的速率,即达到了限流的目的。 在Sentinel中,令牌桶算法主要用于流量控制。Sentinel 提供了`com.alibaba.csp.sentinel.slots.block.flow.TokenBucket`类作为令牌桶算法的实现,配合相关的流量控制模块,可以根据预设的限流规则来决定是否允许请求通过。 以下是一个简化版的Sentinel令牌桶算法使用示例,展示了如何创建一个令牌桶并模拟请求处理过程: import com.alibaba.csp.sentinel.slots.block.flow.TokenBucket; public class SentinelTokenBucketDemo { // 创建一个令牌桶,参数分别为:桶容量、令牌生成速率(每秒添加多少令牌)、是否支持预热 TokenBucket tokenBucket = new TokenBucket(100, 10, false); public void processRequest() { // 获取当前时间 long currentTimeMillis = System.currentTimeMillis(); // 尝试获取令牌 if (tokenBucket.tryAcquire(currentTimeMillis)) { // 请求通过,处理业务逻辑 System.out.println("请求已被处理"); } else { // 没有足够的令牌,请求被拒绝 System.out.println("请求被限流,未处理"); } } public static void main(String[] args) { SentinelTokenBucketDemo demo = new SentinelTokenBucketDemo(); // 模拟连续的请求 for (int i = 0; i < 200; i ) { demo.processRequest(); // 模拟每个请求之间有一定的间隔(这里简化处理,真实情况下由系统自动控制时间间隔) } } } ``` 上述代码中,`TokenBucket`的`tryAcquire`方法会根据当前时间和令牌桶的状态尝试获取令牌,成功则表示请求可以通过,失败则代表请求被限流。注意在实际的Sentinel应用中,你不会直接创建和操作`TokenBucket`对象,而是通过Sentinel API或注解等方式配置和使用令牌桶算法进行流量控制。 在实际的Sentinel项目中,通常我们会通过配置限流规则,并让Sentinel框架自动管理令牌桶和请求的处理,例如: import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; public class SentinelFlowControlDemo { public static void main(String[] args) { // 添加一个限流规则 FlowRule rule = new FlowRule("resourceId") .setCount(10) // 设置每秒最多10个请求通过 .setGrade(RuleConstant.FLOW_GRADE_TOKEN_BUCKET); // 使用令牌桶算法 FlowRuleManager.loadRules(Arrays.asList(rule)); while (true) { try (Entry entry = SphU.entry("resourceId")) { // 处理请求逻辑 processRequest(); } catch (BlockException e) { // 被限流,记录日志或执行降级逻辑 System.out.println("请求被限流"); } } } public static void processRequest() { // ... 业务处理逻辑 } } ``` 在这个例子中,我们首先设置了针对资源ID为`resourceId`的一个令牌桶限流规则,然后在每次请求处理之前使用`SphU.entry`来尝试获取资源准入许可,如果被限流则捕获到`BlockException`异常。
Sentinel 使用令牌桶算法来进行流量控制,并结合滑动窗口统计指标来判断是否应该开启熔断。它具备实时监控、动态规则配置以及丰富的控制台界面,能够方便地观察服务状态、设置和调整熔断降级规则。
具体步骤包括:
1. 配置熔断降级规则,定义资源名称、阈值策略(如QPS、RT等)、熔断后的行为(如快速失败、降级策略等)。
2. 在客户端代码中对需要保护的方法添加Sentinel注解或API调用,以便Sentinel能够拦截并管理这些调用。
3. Sentinel 控制台提供动态管理和控制能力,允许运维人员实时调整规则,查看监控数据。
4. 服务端在接收到请求时,Sentinel 框架依据当前规则进行判断,若满足熔断条件则执行降级策略,否则正常调用下游服务。
总结来说,Sentinel 通过实时统计监控服务间的调用情况,利用熔断和降级机制确保服务稳定性,有效防止因为局部问题导致整体服务的瘫痪,从而提升了微服务架构的健壮性。