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

springcloud篇5-微服务保护(Sentinel)

一、Sentinel

1.1 雪崩问题

在这里插入图片描述
当一个服务依赖多个其他服务时(如上图),当服务D出故障时,无法响应服务A的请求,服务阻塞,不会释放tomcat连接。
当服务A中有多个依赖于服务D的请求传来时,会占用多个tomcat连接,最终导致tomcat资源耗尽:
在这里插入图片描述
当在一个微服务链路中,一个服务出故障可能导致整个链路的所有服务都不可用(多米诺骨牌),这就是雪崩。
在这里插入图片描述

1.1.1 解决雪崩问题的常见方式

(1)超时处理

设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待(不是根本解决办法,当超时时间内传来大量请求时还是会导致雪崩)。

(2)舱壁模式

给每个业务设置线程池,限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离。
在这里插入图片描述
例如,上图中服务A的业务1和2都使用线程池,设置线程数量为10,当服务C出故障时,服务A最多向服务C发送10个请求,不会导致tomcat资源耗尽。
注意:该方法解决了雪崩问题,但是降低了资源利用率。

(3)熔断降级

由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。
在这里插入图片描述

(4)流量控制(sentinel)

限制业务访问的QPS,避免服务因流量的突增而故障。该方法使用sentinel,可以按照服务所能承受的频率释放请求。
在这里插入图片描述

1.2 服务保护技术对比

在这里插入图片描述
隔离策略:线程池隔离类似于舱壁模式。信号量隔离是不会为业务创建线程池,而是统计当前业务使用的线程数,限制数量,当达到阈值后再阻止。

1.3 Sentinel

官网地址:https://sentinelguard.io/zh-cn/index.html
在这里插入图片描述

1.3.1 安装sentinel控制台

在这里插入图片描述
在这里插入图片描述

java -jar sentinel-dashboard-1.8.1.jar

在这里插入图片描述
在这里插入图片描述

sentinel内部提供了很多配置项,可以在运行jar修改参数信息:
在这里插入图片描述

1.3.2 导入项目cloud-demo

(springcloud篇1、篇2的项目)

在这里插入图片描述

1.3.3 微服务整合sentinel

在这里插入图片描述
(一)order-service服务中引入sentinel依赖

在这里插入图片描述

<!-- 引入sentinel依赖 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

(二)order-service配置文件中配置sentinel控制台地址
在这里插入图片描述

    sentinel:transport:dashboard: localhost:8080 #sentinel控制台地址

(三)访问微服务的任意端点,触发sentinel监控
确保user-service、order-service、sentinel与nacos服务启动成功。
在这里插入图片描述
在这里插入图片描述

二、sentinel限流规则

之前提到的雪崩问题提出了四种解决方案,sentinel可以实现其中的三种(流量控制、舱壁模式和熔断降级)

2.1 簇点链路

簇点链路:就是项目中的调用链路(如从controller到service到mapper),链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点,因此SpringMVC的每一个端点就是调用链路中的一个资源。

2.1.1 sentinel限流规则设置

对于1.3.3中微服务整合sentinel的测试中,一次http://localhost:8083/order/103的请求,sentinel的簇点链路监控如下:
在这里插入图片描述
流控、熔断等都是针对簇点链路中的资源来设置的,从上图中可以看到,我们可以通过点击对应资源后面的按钮来设置规则。
比如,点击“流控”按钮:
在这里插入图片描述
在这里插入图片描述
资源名默认。
针对来源:设置从哪里发来的请求需要被限制,default表示一切进来的请求都要被限制。
阈值类型:一般选QPS(并发量,即每秒钟请求的数量)。
单机阈值:即QPS的上限(为1即表示每秒钟最多处理一个请求,超出的请求会被拦截并报错)。

2.1.2 案例

在这里插入图片描述
(一)sentinel设置流控规则
在这里插入图片描述
在这里插入图片描述
(二)使用jmeter进行测试
打开学习资料中已经写好的测试计划:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图中的第一个测试计划为:2秒钟发送20次请求(QPS为10)。
右键启动:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

补充1:sentinel限流规则高级模式

在这里插入图片描述
在这里插入图片描述

1.流控模式
(1)直接(默认)

统计当前资源的请求,触发阈值时对当前资源直接限流。

(2)关联

统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流。
关联模式使用场景:
在这里插入图片描述
配置方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    @GetMapping("/query")public String queryOrder() {return "查询订单成功";}@GetMapping("/update")public String updateOrder() {return "更新订单成功";}

重启服务,在浏览器中分别发送请求:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在上述请求运行时去访问query:
在这里插入图片描述
可以看到,query请求被sentinel限制了。

(3)链路

统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流。
在这里插入图片描述
案例如下:
在这里插入图片描述
在这里插入图片描述

    public void queryGoods(){System.err.println("查询商品");}

在这里插入图片描述

    @GetMapping("/query")public String queryOrder() {// 查询商品orderService.queryGoods();// 查询订单System.err.println("查询订单");return "查询订单成功";}@GetMapping("/save")public String saveOrder() {// 查询商品orderService.queryGoods();// 查询订单System.err.println("新增订单");return "新增订单成功";}

注意:
(1)sentinel只默认标记controller中的方法为资源,如果要标记其他方法(比如service中的方法),需要使用@SentinelResource注解。
在这里插入图片描述
在这里插入图片描述
(2)sentinel默认会将controller方法做context整合,导致链路模式的流控失效,需需要修改sentinel配置:
在这里插入图片描述
在这里插入图片描述

web-context-unify: false # 关闭context整合

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:上图中的goods时同一个资源,任意选择一个进行配置即可。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
启动上面的测试任务:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.流控效果

流控效果是指请求达到流控阈值时应该采取的措施,包括3种。

(1)快速失败(默认)

指达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。

(2)warm up

预热模式,对超出阈值的请求同样是拒绝并抛出异常,但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。
是应对服务冷启动(服务刚启动就达到阈值可能会使服务响应不了)的一种方案。请求阈值初始值是threshold/coldFactor(coldFactor默认为3),持续指定时长后,逐渐提高到threshold值。
在这里插入图片描述
一个案例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)排队等待

让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长。设置一个超时时间,若是在队列中等待的时间超时,则会抛出异常。
在这里插入图片描述
一个案例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到接收的QPS是稳定的。

补充2:热点参数限流

之前的限流都是统计访问某个资源的所有请求,判断是否超过QPS阈值。而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。
在这里插入图片描述
在这里插入图片描述
一个例子:
在这里插入图片描述
注意:热点参数限流对springmvc默认资源无效,需要加@SentinelResource注解。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结果如下:
在这里插入图片描述
注意:单机阈值为2。
在这里插入图片描述
在这里插入图片描述

三、 隔离和降级

3.1 feign与sentinel整合

隔离和降级即舱壁模式(线程隔离)。
从前面可知,不论是线程隔离还是熔断降级,都是对客户端(调用方)的保护。springcloud中远程调用使用feign,所以线程隔离和熔断降级使用feign整合sentinel的模式。
步骤:
在这里插入图片描述
(一)在调用者(order-service,被调用者是user-service)中开启feign对sentinel的支持
在这里插入图片描述

  sentinel:enabled: true # 开启feign对sentinel的支持

(二)给FeignClient(feign-api服务)编写失败后的降级逻辑FallBackFactory
在这里插入图片描述

import cn.itcast.feign.clients.UserClient;
import cn.itcast.feign.pojo.User;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {@Overridepublic UserClient create(Throwable throwable) {return new UserClient() {@Overridepublic User findById(Long id) {log.error("查询用户异常", throwable);return new User();}};}
}

回忆一下之前写的UserClient:
在这里插入图片描述
(三)注册写好的FallbackFactory
在这里插入图片描述

    @Beanpublic UserClientFallbackFactory userClientFallbackFactory(){return new UserClientFallbackFactory();}

(四)在Userlient注解上声明FallbackFactory

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 线程隔离

线程隔离有两种实现方式:
(1)线程池隔离
在这里插入图片描述
(2)信号量隔离(sentinel默认采用)
在这里插入图片描述
不会创建新的线程,使用原来处理请求的线程。一个请求信号量的计数器减1,业务处理完信号量加1,计数器为0时再有请求会被拒绝。
在这里插入图片描述
一个案例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 熔断降级

由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。
在这里插入图片描述
熔断器熔断(closed状态到Open状态即2)策略有三种:慢调用、异常比例、异常数

3.3.1慢调用

在这里插入图片描述
一个例子:
在这里插入图片描述
在这里插入图片描述

    @GetMapping("/{id}")public User queryById(@PathVariable("id") Long id,@RequestHeader(value = "Truth", required = false) String truth) throws InterruptedException {if(id==1){//休眠60毫秒,触发熔断Thread.sleep(60);}return userService.queryById(id);}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
执行完jmeter测试任务后,访问102查不到用户,即触发了熔断:
在这里插入图片描述

3.3.2异常比例和异常数

在这里插入图片描述
在这里插入图片描述

    @GetMapping("/{id}")public User queryById(@PathVariable("id") Long id,@RequestHeader(value = "Truth", required = false) String truth) throws InterruptedException {if(id==1){//休眠60毫秒,触发熔断Thread.sleep(60);}else if(id==2){throw new RuntimeException("故意出错,触发熔断");}return userService.queryById(id);}

降级策略按例子配置,这里不在举例了。

四、授权规则

4.1 sentinel授权规则配置

针对绕过网关直接访问微服务的情况(当然这是异常情况,只是多加一层保护)。
在这里插入图片描述
在这里插入图片描述
(一)新增继承RequestOriginParser的类

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;@Component
public class HeaderOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest request){// 1.获取请求头String origin = request.getHeader("Origin");//2.非空判断if(StringUtils.isEmpty(origin)){origin = "blank";}return origin;}
}

(二)修改gateway服务,给所有请求增加请求头origin
在这里插入图片描述

      default-filters:- AddRequestHeader=origin,gateway

重启order-service服务和gateway服务。
(三)在sentinel控制台添加授权规则
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2 自定义异常结果

默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。如果要自定义异常时的返回结果,需要实现BlockExceptionHandler接口。
在这里插入图片描述
可以通过判断BlockException的异常类型从而进行不同的处理,异常类型包括:
在这里插入图片描述
(一)添加继承BlockExceptionHandler的类
在这里插入图片描述

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {String msg = "未知异常";int status = 429;if (e instanceof FlowException) {msg = "请求被限流了";} else if (e instanceof ParamFlowException) {msg = "请求被热点参数限流";} else if (e instanceof DegradeException) {msg = "请求被降级了";} else if (e instanceof AuthorityException) {msg = "没有权限访问";status = 401;}response.setContentType("application/json;charset=utf-8");response.setStatus(status);response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");}
}

重启服务进行测试:
在这里插入图片描述
在这里插入图片描述

4.3 规则持久化

服务重启时,配置与该服务相关的sentinel规则就会消失,这是因为sentine规则l默认保存在内存,生产环境需持久化。
在这里插入图片描述

4.3.1 pull模式

在这里插入图片描述

4.3.2 Push模式

在这里插入图片描述
push模式实现较为复杂,依赖于nacos,并且需要修改sentinel控制台源码。
在这里插入图片描述
具体步骤见资料《sentinel规则持久化.md》:
在这里插入图片描述

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

相关文章:

  • Spring Boot mybatis-plus 多数据源配置
  • 【CVE-2025-5419】(内附EXP) Google Chrome 越界读写漏洞【内附EXP】
  • Kafka面试精讲 Day 1:Kafka核心概念与分布式架构
  • Elasticsearch中的协调节点
  • 详解kafka基础(一)
  • JavaScript常用的算法详解
  • Cherry-pick冲突与Git回滚
  • Oracle跟踪及分析方法
  • 力扣100+补充大完结
  • MySql 事务 锁
  • 推荐系统学习笔记(十四)-粗排三塔模型
  • 庖丁解牛:深入解析Oracle SQL语言的四大分类——DML、DDL、DCL、TCL
  • KubeBlocks for Oracle 容器化之路
  • 高校党建系统设计与实现(代码+数据库+LW)
  • 从零开始的 Docker 之旅
  • HIVE的高频面试UDTF函数
  • 【软考论文】论面向对象建模方法(动态、静态)
  • 无人机倾斜摄影农田航线规划
  • HTML应用指南:利用GET请求获取中国银行人民币存款利率数据
  • SciPy科学计算与应用:SciPy线性代数模块入门-矩阵运算与应用
  • 精确位置定位,AR交互助力高效作业流程​
  • 余承东:鸿蒙智行累计交付突破90万辆
  • 机器人视频感知架构深度解析:7条技术法则,打造低延迟实时感知与交互
  • 【ROS2】 忽略局域网多机通信导致数据接收的bug
  • 天气查询小程序项目报告
  • iOS 审核 4.3a【二进制加固】
  • Spring MVC 全解析:从核心原理到 SSM 整合实战 (附完整源码)
  • leetcode-python-383赎金信
  • 深度学习----由手写数字识别案例来认识PyTorch框架
  • 构建AI智能体:十四、从“计算”到“洞察”:AI大模型如何让时间序列数据“开口说话”