当前位置: 首页 > news >正文

SpringCloud Alibaba Sentinel 流量治理、熔断限流(四)

目录

一 概念引入

二 运作流程

三 使用

四 异常处理

1 拦截器全局兜底

2 指定资源方法兜底 blockHandler/fallbcak

3 远程调用的兜底 Fallback

4 sphu硬编码

五 几种常用的控制规则

1 流控规则

2 熔断规则

3 热点规则

4 授权规则

5 系统规则


一 概念引入

二 运作流程

三 使用

下载对应的jar包:

java -jar sentinel-dashboard-1.8.8.jar

Release v1.8.8 · alibaba/Sentinel

这里的默认端口是8080,最好与本地的启动端口进行区分

默认账号密码均为sentinel

在本地项目当中进行相对应的配置

spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.eager=true

重新启动项目展示:

四 异常处理

核心优先级总结

  1. 优先执行方法级别的兜底(blockHandler

  2. 如果方法没有兜底,才会进入 全局 BlockExceptionHandler

  3. 如果既没有 @SentinelResource,也没有全局拦截器,那么异常会直接抛到调用方(用户就看到 500 错误页了 )。

三个层级:

1 拦截器全局兜底

代码定义:@SentinelResource注解

    @SentinelResource("createOrder")@Overridepublic Order createOrder(Long productId, Long userId) {// Product product = getProductFromRemote3(productId);Product product = productFeignClient.getProductById(productId);Order order = new Order();order.setId(1L);// 远程调用计算商品数额order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("张三");order.setAddress("青岛");// 远程调用获取商品信息order.setProductList(Arrays.asList(product));return order;}

控制台:进行限流

页面展示:限流结束

拦截器:自定义拦截器的返回规则

package com.ax.order.exception;import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.ax.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;import java.io.PrintWriter;@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {private final ObjectMapper objectMapper = new ObjectMapper();@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,String s, BlockException e) throws Exception {httpServletResponse.setContentType("application/json;charset=utf-8");PrintWriter writer = httpServletResponse.getWriter();R error = R.error(500, s + "被Sentinel 给限流了" + e.getClass());String s1 = objectMapper.writeValueAsString(error);writer.write(s1);writer.flush();}
}

效果展示:

2 指定资源方法兜底 blockHandler/fallbcak

代码实现:

    // sentinel有两种情况,正常则返回,异常则调用blockHandler指定的方法@SentinelResource(value = "createOrder", blockHandler = "createOrderFallback")@Overridepublic Order createOrder(Long productId, Long userId) {// Product product = getProductFromRemote3(productId);Product product = productFeignClient.getProductById(productId);Order order = new Order();order.setId(1L);// 远程调用计算商品数额order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("张三");order.setAddress("青岛");// 远程调用获取商品信息order.setProductList(Arrays.asList(product));return order;}//兜底回调public Order createOrderFallback(Long productId, Long userId, BlockException e) {Order order = new Order();order.setId(1L);order.setTotalAmount(new BigDecimal(0));order.setUserId(userId);order.setNickName("未知用户");order.setAddress("异常信息" + e.getMessage());order.setProductList(null);return order;}
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.Arrays;@Service
public class OrderServiceImpl implements OrderService {@SentinelResource(value = "createOrder",blockHandler = "createOrderBlockHandler",  // 限流、熔断时走这里fallback = "createOrderFallback"           // 业务异常时走这里)@Overridepublic Order createOrder(Long productId, Long userId) {// 模拟远程调用商品服务Product product = productFeignClient.getProductById(productId);// 模拟异常(比如商品服务挂了)if (product == null) {throw new RuntimeException("商品不存在或服务不可用");}Order order = new Order();order.setId(1L);order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("张三");order.setAddress("青岛");order.setProductList(Arrays.asList(product));return order;}/*** blockHandler: 处理 Sentinel 限流/熔断/系统保护* 触发条件:流量超限、熔断等情况*/public Order createOrderBlockHandler(Long productId, Long userId, BlockException e) {Order order = new Order();order.setId(-1L);order.setTotalAmount(BigDecimal.ZERO);order.setUserId(userId);order.setNickName("系统繁忙");order.setAddress("触发流控/熔断:" + e.getClass().getSimpleName());order.setProductList(null);return order;}/*** fallback: 处理业务异常(运行时异常)* 触发条件:代码运行报错,如空指针、远程调用异常*/public Order createOrderFallback(Long productId, Long userId, Throwable e) {Order order = new Order();order.setId(-2L);order.setTotalAmount(BigDecimal.ZERO);order.setUserId(userId);order.setNickName("未知用户");order.setAddress("业务异常兜底:" + e.getMessage());order.setProductList(null);return order;}
}

1 如果是流量过大 / 系统保护(Sentinel 规则触发) → blockHandler

例子:秒杀活动、热点参数限流。

作用:告诉用户“当前排队人数过多,请稍后再试”。

2 如果是业务逻辑异常fallback

例子:远程调用下游服务失败(商品服务挂了)、数据处理出现异常。

作用:返回一个默认结果或缓存数据,保证系统可用性。

3 两者可以配合使用

blockHandler → 处理 限流/熔断

fallback → 处理 业务异常

Sentinel 会优先调用 blockHandler,如果没有配置,再进入 fallback

3 远程调用的兜底 Fallback

package com.ax.order.feign;import com.ax.order.feign.fallback.ProductFeignClientFallback;
import com.ax.product.bean.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(name = "service-product", fallback = ProductFeignClientFallback.class)
public interface ProductFeignClient {/*** 测试FeignClient** @param id*///mvc注解两套使用逻辑//标注在Controller上,为接收请求//标注在FeignClient上,为发送请求@GetMapping("/product/{id}")Product getProductById(@PathVariable("id") Long id);//如果调用自己其他服务的api直接将其方法复制过来即可,下面这个就是从product当中复制过来的//    @GetMapping("/product/{id}")//    Product getProduct(@PathVariable("id") Long id);
}

回调:

package com.ax.order.feign.fallback;import com.ax.order.feign.ProductFeignClient;
import com.ax.product.bean.Product;
import org.springframework.stereotype.Component;import java.math.BigDecimal;@Component
public class ProductFeignClientFallback implements ProductFeignClient {@Overridepublic Product getProductById(Long id) {System.out.println("兜底回调");Product product = new Product();product.setId(id);product.setProductName("商品不存在");product.setNum(0);product.setPrice(new BigDecimal("0.0"));return product;}
}

4 sphu硬编码

这个硬编码方式就是使用 SphU.entry() 来定义一个资源,配合 try-with-resources 或者 try-catch-finally 来做 限流、熔断、降级 控制。

五 几种常用的控制规则

1 流控规则

单机模式

流控规则:限制多余请求,从而保护系统资源不被耗尽。

资源名:标识限流规则的目标对象。

针对来源:看可以对不同来源设置不同的规则。

阈值类型:单机维度:QPS指的是秒请求数。并发线程数指的是秒请求线程数。

流控模式:触发条件

1 直接:对当前资源本身进行限流。2 关联:不仅受到当前资源的影响,如果当前资源下的调用消耗也大,将会将当前资源进行限流。3 链路:只对特定调用链路中的资源进行限流。

流控效果:超限之后如何处理

1 快速失败:直接返回异常 2 预热模式:防止项目的冷启动(项目启动后会慢慢的提升,不会直接到预定值,而是在指定时间内达到) 3 排队等待:超过阈值的进入等待队列,按照顺序依次排队执行。  

关联:给readDb加流控,关联资源是writeDb,表面上是对readDb加流量管控,但是其大量请求并没有影响,影响的前提是writeDb的请求较大,那么就会将readDb进行限制

链路:(比如一个方法被多个地方引用,可以指定其具体的一个链路,比如说秒杀与退货,两个都有对数据库当中数据查询,那么就可以指定秒杀的链路进行流控)

集群模式

集群阈值模式:1 单机均摊:配置的阈值会按照机器数量平分到每台机器。2 总体阈值:阈值是所有的机器总和。

失败退化:当 Token Server 不可用时,是否自动退化为 单机限流。

上下文统一

  • web-context-unify: 主要用于 是否启用统一的 Web 上下文处理

  • 如果设置为 true

    • 系统会对所有的 HTTP 响应做统一封装(比如统一响应格式、统一异常处理)。

    • 方便前端统一处理接口返回数据和错误码。

  • 如果设置为 false

    • 不做统一封装,接口返回什么就原样返回。

    • 适合需要原始返回结构或者第三方接口调用的场景

2 熔断规则

核心作用:熔断降级作为保护自身的手段,通常在客户端进行配置,便于更好的获得数据或者执行业务。

1 切断不稳定调用:通过持续监控下游服务的调用指标(如异常比例、响应时长),当故障超过预设阈值时,熔断器将自动开启,立即切断所有请求,防止问题蔓延。

2 快速返回不积压:熔断开启后,所有后续请求不再尝试访问故障服务,而是在本地即刻返回失败响应。此举能有效避免请求线程阻塞和资源堆积,保护调用方自身资源不被耗尽。

3 避免雪崩:将故障服务隔离在调用链之外,将其影响范围限制在局部,有效阻止了单个后端的故障向上蔓延,从而保障整个分布式系统的稳定性和高可用性,避免系统性崩溃。

断路器

工作原理

三个状态:关闭,半开,打开

这个状态机模型实现了一个全自动的、智能的故障隔离与恢复循环

  1. 正常期:(Closed) 监控流量,一切正常。

  2. 故障检测:监控指标超标 -> 触发熔断 -> (Open) 快速失败,保护系统。

  3. 恢复试探:熔断时间到 -> (Half-Open) 放行探测请求。

  4. 恢复成功:探测成功 -> 回到 (Closed) 状态,系统恢复正常。

  5. 恢复失败:探测失败 -> 回到 (Open) 状态,继续熔断。

三个参数:慢调用比例,异常比例,异常数

慢调用比例:

最大RT:相当于响应时间,超过则为慢请求。1000ms

比例阈值:超过多少比例的请求为慢请求的条件。0-1

熔断时长:熔断时长。1s

最小请求数:达到一定的数量级才可以满足。

异常比例:

比例阈值:调用出现异常的比例。0-1

熔断时长:熔断时长。1s

最小请求数:达到一定数量级才可以满足。

异常数

异常数:出现异常的数量

熔断时长:熔断时长。1s

最小请求数:达到一定数量级才可以满足。

3 热点规则

热点规则:在原有的流控的基础之上,可以实现更加精细化的流量控制,不是对某个资源的一刀切,而是智能的识别出“热点参数”并对其实施特殊关照(限流操作,可以结合前面的兜底处理)。

展示:注意required=false的使用

4 授权规则

5 系统规则

http://www.dtcms.com/a/359030.html

相关文章:

  • 【源码】智慧工地系统:智能化施工现场的全新管理方案
  • 第十七章 ESP32S3 SW_PWM 实验
  • 深入解析Nginx常见模块2
  • web渗透之RCE漏洞
  • 针对 “TCP 会话维持与身份验证” 的攻击
  • (二)设计模式(Command)
  • SQL Server 临时表合并与数量汇总的实现方法
  • 大模型不听话?试试提示词微调
  • “可选功能“中找不到 OpenSSH, PowerShell 命令行来安装OpenSSH
  • windows 谷歌浏览器一直提示无法更新Chrome弹窗问题彻底解决
  • Learning Curve|学习曲线
  • 数据库攻略:“CMU 15-445”Project0:C++ Primer(2024 Fall)
  • 【开题答辩全过程】以 “与我同行”中华传统历史数字化平台的设计和分析-------为例,包含答辩的问题和答案
  • Linux软件定时器回顾
  • 本地部署开源媒体服务器 Komga 并实现外部访问( Windows 版本)
  • 容器存储驱动升级:美国VPS文件系统优化全指南
  • 上海我店模式的多维度探究
  • 对于STM32工程模板
  • CRM、ERP、HRP系统有啥区别?
  • 250830-Docker从Rootless到Rootful的Gitlab镜像迁移
  • 深刻理解软硬件链接
  • ubuntu24.04 qt6安装
  • 学习游戏制作记录(各种优化)
  • 复制VMware虚拟机后的网络配置
  • leetcode算法刷题的第二十二天
  • 论《运动战》
  • Linux查看有线网卡和无线网卡详解
  • UNet改进(36):融合FSATFusion的医学图像分割
  • Vue基础知识-单向绑定v-bind、双向绑定v-model、插值语法{{}}、Object.defineProperty实现数据代理
  • PostgreSQL数据类型一览(数值类型)