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

浅聊一下微服务的服务保护

在微服务架构里,服务间调用关系错综复杂,一个服务出问题很可能引发连锁反应,也就是 “雪崩”。今天就带大家从零开始学习 Sentinel,这款阿里开源的微服务保护工具,帮你解决雪崩难题,做好流量控制、隔离降级。

一、初识 Sentinel:先搞懂雪崩和解决方案

1.1 雪崩问题到底是啥?

微服务中,一个服务往往依赖多个其他服务。比如服务 A 依赖服务 B,服务 B 又依赖服务 C。要是服务 C 故障了,服务 B 调用 C 时会阻塞,服务 A 调用 B 也会跟着阻塞。

服务器的线程和并发数是有限的,一旦大量请求阻塞,服务器资源很快就会耗尽,进而导致所有服务不可用。接着,依赖这些服务的其他服务也会陆续 “挂掉”,形成级联失败 —— 这就是雪崩。

1.2 解决雪崩的 4 种核心方案

既然雪崩这么可怕,那怎么防?主要有 4 种思路:

  • 超时处理:给请求设个超时时间,超过时间没响应就返回错误,别一直等。比如调用一个服务,超过 200ms 就直接提示 “请求超时”,避免线程一直占用。
  • 仓壁模式(线程隔离):像船舱的防水隔板一样,给每个业务分配独立的线程池。比如订单业务用 10 个线程,商品业务用 10 个线程,就算订单业务线程耗尽,也不影响商品业务。
  • 断路器:统计服务调用的异常比例,要是超过阈值(比如异常率 50%),就 “熔断”—— 暂时拦截所有访问该服务的请求,等服务恢复了再放行。
  • 限流:限制服务的 QPS(每秒请求数),比如每秒最多处理 100 个请求,超过的直接拒绝,避免突发流量把服务冲垮。

简单总结下:限流是 “预防”,提前挡住过多流量;超时、仓壁、断路器是 “补救”,故障发生时控制影响范围。

1.3 服务保护工具对比:为啥选 Sentinel?

Spring Cloud 里有 Hystrix、Resilience4J、Sentinel 等工具,国内用得最多的是 Sentinel,对比 Hystrix 优势很明显:

对比项SentinelHystrix
隔离策略信号量隔离线程池 / 信号量隔离
熔断策略慢调用 / 异常比例失败比率
流量整形支持预热、排队等待不支持
控制台开箱即用,秒级监控不完善
生态适配Spring Cloud、Dubbo 等主要适配 Spring Cloud Netflix

Sentinel 不仅功能全,还能承接阿里双十一大促的流量,稳定性有保障,这也是咱们选它的核心原因。

1.4 Sentinel 安装:3 步搞定

Sentinel 有个可视化控制台,能配置规则、看监控,安装特别简单:

  1. 下载 jar 包:去 GitHub 搜 “Sentinel”,下载最新的 dashboard jar 包(比如 sentinel-dashboard-1.8.1.jar)。
  2. 运行 jar 包:把 jar 包放到非中文目录,打开命令行执行:
    # 默认端口8080,账号密码都是sentinel
    java -jar sentinel-dashboard-1.8.1.jar
    # 想改端口的话,比如改到8090
    java -Dserver.port=8090 -jar sentinel-dashboard-1.8.1.jar
    
  3. 访问控制台:打开浏览器输http://localhost:8080,输入账号密码(都是 sentinel)就能进。刚进去是空白的,因为还没整合微服务。

1.5 微服务整合 Sentinel:以 order-service 为例

以订单服务(shop-order)为例,整合 Sentinel 就 3 步:

  1. 加依赖:在 pom.xml 里加 Sentinel 依赖:
    <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    
  2. 配控制台地址:在 application.yaml 里加配置,告诉服务控制台在哪:
    spring:cloud:sentinel:transport:dashboard: localhost:8080 # 控制台地址
    
  3. 触发监控:启动服务后,访问一个接口(比如http://localhost:8091/order/prod/19),再刷新控制台,就能看到服务的监控数据了。

二、流量控制:提前挡住突发流量

限流是预防雪崩的关键,Sentinel 的流量控制功能很强大,咱们从基础到进阶慢慢讲。

2.1 先认识 “簇点链路”

请求进微服务时,会走DispatcherServlet → Controller → Service → Mapper这样的调用链,这就是 “簇点链路”。链路上的每个接口(比如 Controller 的方法)都是一个 “资源”,Sentinel 默认会监控 SpringMVC 的所有接口。

在控制台的 “簇点链路” 菜单里,能看到所有资源,每个资源后面都有 “流控”“降级” 等按钮,点进去就能配置规则。

2.2 流控快速入门:给接口设 QPS 阈值

比如给/order/prod/{pid}这个接口设限流规则:QPS 不超过 5(每秒最多 5 个请求)。

  1. 加规则:在簇点链路里,找到/order/prod/{pid},点后面的 “流控”,配置:
    • 阈值类型:QPS
    • 单机阈值:5
    • 其他默认,点 “新增”。
  2. 用 Jmeter 测试:建个线程组,20 个用户、2 秒内发完(QPS=10,超过 5)。运行后看结果,每秒只会成功 5 个请求,超过的会被拒绝。

2.3 3 种流控模式:应对不同场景

流控模式是指 “什么时候触发限流”,Sentinel 支持 3 种,咱们结合场景讲:

2.3.1 直接模式:默认模式,对当前资源限流

刚才的快速入门就是直接模式 —— 只要当前资源的 QPS 超过阈值,就直接限流。适合简单的接口保护,比如普通查询接口。

2.3.2 关联模式:高优先级资源优先,限流低优先级

场景:比如订单的 “更新”(/order/update)和 “查询”(/order/query)都操作数据库,更新要优先保证,要是更新请求太多,就限流查询。

  1. 加接口:在 OrderController 里加两个接口:
    // 查询订单
    @GetMapping("/order/query")
    public String queryOrder() {return "查询订单成功";
    }
    // 更新订单
    @GetMapping("/order/update")
    public String updateOrder() {return "更新订单成功";
    }
    
  2. 配规则:给/order/query加关联流控规则:
    • 流控模式:关联
    • 关联资源:/order/update(当更新接口 QPS 超 5 时,限流查询)
    • 阈值:5
  3. 测试:用 Jmeter 压/order/update(QPS=10),再用浏览器访问/order/query,会提示 “Blocked by Sentinel (flow limiting)”—— 查询被限流了。
2.3.3 链路模式:只限流指定来源的请求

场景:查询订单(/order/query)和创建订单(/order/save)都要调用 “查询商品”(queryGoods)方法,只想限流从 “查询订单” 进来的请求。

  1. 加方法和接口
    • OrderService 加 queryGoods 方法,用@SentinelResource("goods")标记(让 Sentinel 监控):
      @SentinelResource("goods")
      public void queryGoods() {System.err.println("查询商品");
      }
      
    • OrderController 加/order/save,并让/order/query/order/save都调用 queryGoods:
      // 查询订单调用商品查询
      @GetMapping("/order/query")
      public String queryOrder() {orderService.queryGoods();return "查询订单成功";
      }
      // 新增订单调用商品查询
      @GetMapping("/order/save")
      public String saveOrder() {orderService.queryGoods();return "新增订单成功";
      }
      
  2. 关资源聚合:Sentinel 默认会把 SpringMVC 请求聚合到一个 root 资源,链路模式会失效,所以要在 application.yaml 里关了:

    yaml

    spring:cloud:sentinel:web-context-unify: false # 关闭context整合
    
  3. 配规则:给 “goods” 资源加链路流控规则:
    • 流控模式:链路
    • 入口资源:/order/query(只统计从查询订单进来的请求)
    • 阈值:2
  4. 测试:用 Jmeter 压/order/save(QPS=4),访问/order/save正常;压/order/query(QPS=4),超过 2 的请求会被限流。

2.4 3 种流控效果:超过阈值后怎么处理?

流控效果是指 “QPS 超阈值后,怎么处理新请求”,Sentinel 支持 3 种:

2.4.1 warm up(预热模式):应对服务冷启动

服务刚启动时,资源没初始化(比如连接池没建立),要是直接扛最大 QPS,可能会宕机。预热模式就是让阈值从一个小值慢慢涨到最大值,给服务 “预热” 时间。

比如给/order/prod/{pid}设规则:

  • 阈值类型:QPS
  • 单机阈值:10(最大 QPS)
  • 流控效果:warm up
  • 预热时长:5 秒

Sentinel 默认冷启动因子是 3,所以初始阈值是 10/3≈3。刚启动时,每秒只能过 3 个请求,5 秒后慢慢涨到 10 个。用 Jmeter 测试,刚开始失败率高,后来会越来越低。

2.4.2 排队等待:让请求平滑执行

快速失败和 warm up 都是直接拒绝超阈值请求,排队等待则是让请求排队,按固定间隔执行,避免流量波动。

比如给/order/prod/{pid}设规则:

  • 阈值类型:QPS
  • 单机阈值:10(每秒 10 个,即每 200ms 一个)
  • 流控效果:排队等待
  • 超时时间:5000ms(请求等待超过 5 秒就拒绝)

用 Jmeter 压 QPS=15(超阈值),结果所有请求都会通过,但响应时间会变长 —— 因为都在排队。控制台看 QPS 曲线会很平滑,一直保持在 10 左右,对服务器很友好。

2.4.3 快速失败:默认效果,直接拒绝

超过阈值后,新请求直接被拒绝,抛出FlowException,适合对响应时间敏感的场景(比如支付接口,不能让用户等)。

2.5 热点参数限流:对不同参数区别对待

之前的限流是统计整个资源的 QPS,热点参数限流则是按 “参数值” 统计。比如/order/prod/{pid}接口,pid=1 是秒杀商品(热点),pid=2 是普通商品,想给它们设不同的 QPS 阈值。

2.5.1 实战案例:给 pid 设不同阈值

需求:/order/prod/{pid}默认 QPS=2,pid=1 设 QPS=4,pid=19 设 QPS=10。

  1. 标记资源:给接口加@SentinelResource("hot")(热点限流要这个注解):
    @SentinelResource("hot")
    @GetMapping("/order/prod/{pid}")
    public String getOrderByPid(@PathVariable Integer pid) {// 业务逻辑
    }
    
  2. 加热点规则:控制台进 “热点规则”,点 “新增”:
    • 资源名:hot
    • 限流模式:QPS 模式
    • 参数索引:0(第一个参数,即 pid)
    • 单机阈值:2(默认阈值)
    • 高级选项→参数例外项:
      • 加 pid=1(long 类型),阈值 4
      • 加 pid=19(long 类型),阈值 10
  3. 测试:用 Jmeter 分别压 pid=1(QPS=5)、pid=19(QPS=12)、普通 pid(QPS=3):
    • pid=1:每秒成功 4 个
    • pid=19:每秒成功 10 个
    • 普通 pid:每秒成功 2 个

三、隔离和降级:故障发生时控制影响范围

限流是预防,隔离和降级是故障发生后的 “止损” 手段。Sentinel 主要通过线程隔离(仓壁模式)和熔断降级来实现。

3.1 Feign 整合 Sentinel:远程调用要保护

微服务远程调用大多用 Feign,所以要先整合 Feign 和 Sentinel,才能在远程调用时做隔离和降级。

3.1.1 开启 Feign 的 Sentinel 支持

在 order-service 的 application.yaml 里加配置:

feign:sentinel:enabled: true # 开启Feign对Sentinel的支持
3.1.2 写失败降级逻辑

远程调用失败时(比如服务宕机),不能直接报错,要返回友好提示。有两种方式:

方式 1:FallbackClass(不支持捕获异常)
  1. 写降级类,实现 Feign 接口:
    @Component
    public class ProductServiceFallback implements IProductService {@Overridepublic Product findByPid(Integer pid) {// 降级逻辑:返回默认值Product product = new Product();product.setPid(-1);product.setPname("暂无商品");return product;}
    }
    
  2. Feign 接口指定降级类:
    @FeignClient(value = "service-product", fallback = ProductServiceFallback.class)
    public interface IProductService {@GetMapping("/product/{pid}")Product findByPid(@PathVariable Integer pid);
    }
    
方式 2:FallbackFactory(支持捕获异常)

要是想知道调用失败的原因,就用 FallbackFactory:

  1. 写降级工厂类:
    @Component
    public class ProductServiceFallbackFactory implements FallbackFactory<IProductService> {@Overridepublic IProductService create(Throwable throwable) {// 打印异常信息System.out.println("调用失败:" + throwable.getMessage());// 返回降级逻辑return new IProductService() {@Overridepublic Product findByPid(Integer pid) {Product product = new Product();product.setPid(-1);product.setPname("暂无商品");return product;}};}
    }
    
  2. Feign 接口指定降级工厂:
    @FeignClient(value = "service-product", fallbackFactory = ProductServiceFallbackFactory.class)
    public interface IProductService {@GetMapping("/product/{pid}")Product findByPid(@PathVariable Integer pid);
    }
    

3.2 线程隔离(仓壁模式):避免资源耗尽

线程隔离是给每个远程调用分配独立的线程池(或信号量),就算某个调用故障,也只消耗该线程池的资源,不影响其他调用。

3.2.1 两种隔离方式对比
隔离方式原理优点缺点
信号量隔离计数器模式,统计线程数简单,开销小不能隔离慢调用
线程池隔离给每个调用分配独立线程池隔离彻底,支持慢调用线程切换开销大

Sentinel 默认用信号量隔离,要是需要隔离慢调用(比如调用一个慢服务),就用线程池隔离。

3.2.2 实战:给 Feign 接口设线程数阈值

需求:order-service 调用 product-service 的接口,线程数不超过 2(即同时最多 2 个线程调用)。

  1. 加规则:在簇点链路里找到 Feign 接口(比如/product/{pid}),点 “流控”:
    • 阈值类型:线程数
    • 单机阈值:2
    • 其他默认
  2. 测试:用 Jmeter 发 10 个并发请求(瞬间发完),会发现部分请求返回降级逻辑(“暂无商品”)—— 因为线程数超 2 了,超出的请求被限流。

3.3 熔断降级:故障服务暂时 “隔离”

要是一个服务调用失败率很高(比如 80% 的请求都失败),继续调用只会浪费资源,这时候就该 “熔断”—— 暂时拦截所有调用,等服务恢复了再放行。

Sentinel 的熔断策略有两种:

  • 慢调用比例:请求响应时间超过 “慢调用阈值” 的比例,超过阈值就熔断。
  • 异常比例:调用失败(抛异常)的比例超过阈值,就熔断。

配置方式和流控类似,在簇点链路里点 “降级”,选对应的策略和阈值即可。比如设 “异常比例”:异常率超过 50%,熔断时长 5 秒 ——5 秒内所有调用都会被拦截,5 秒后会放少量请求试探,要是恢复了就取消熔断。

总结

Sentinel 的核心功能就是 “流量控制” 和 “隔离降级”:

  • 流量控制:通过直接 / 关联 / 链路模式,结合快速失败 /warm up / 排队效果,提前挡住突发流量,预防雪崩。
  • 隔离降级:通过线程隔离(仓壁模式)和熔断降级,在服务故障时控制影响范围,避免级联失败。

实际项目中,要根据业务场景选择合适的规则 —— 比如秒杀接口用 warm up + 热点参数限流,慢服务调用用线程池隔离,核心接口用熔断降级。多测试、多调优,才能让微服务更稳定~


文章转载自:

http://v2htCO26.rgLzy.cn
http://GduszIfO.rgLzy.cn
http://cg4srl7r.rgLzy.cn
http://DYKwn0Dn.rgLzy.cn
http://CSFRzgse.rgLzy.cn
http://jnIzcDWm.rgLzy.cn
http://sz3z8RLh.rgLzy.cn
http://N5V6h3V9.rgLzy.cn
http://5fpppQ3R.rgLzy.cn
http://JiK2rLsz.rgLzy.cn
http://9wpj9cI7.rgLzy.cn
http://59ZlJyvt.rgLzy.cn
http://OwwAH7zq.rgLzy.cn
http://stjfOvNL.rgLzy.cn
http://Qps8wLC7.rgLzy.cn
http://vPCmySkd.rgLzy.cn
http://nMXBEGIg.rgLzy.cn
http://2wXCU7z8.rgLzy.cn
http://TIRvsB5p.rgLzy.cn
http://WDTYSXsq.rgLzy.cn
http://z1Ma9cM0.rgLzy.cn
http://VHzJhYL5.rgLzy.cn
http://NEXF2cR3.rgLzy.cn
http://X5ejHITa.rgLzy.cn
http://twk7P6I2.rgLzy.cn
http://7o5KmZCE.rgLzy.cn
http://sw0oTreb.rgLzy.cn
http://vdba7kIU.rgLzy.cn
http://GTWEt0NP.rgLzy.cn
http://WTz8bYBH.rgLzy.cn
http://www.dtcms.com/a/372718.html

相关文章:

  • Nginx 实战系列(五)—— Nginx流量监控:从stub_status到nginx-module-vts的进阶指南
  • 34. 什么是反射
  • YOLO11 改进、魔改|通道自注意力卷积块CSA-ConvBlock,实现 “轻量化特征增强”
  • 优先搜索(DFS)实战
  • 计算机视觉opencv----银行卡号码识别
  • 第六章、从transformer到nlp大模型:编码器-解码器模型 (Encoder-Decoder)
  • pymodbus启动一个简单的modbus tcp server
  • 【NowCoder】牛客周赛 Round 108 EF (背包问题 | SOSDP)
  • 【ARMday02】
  • OFDR设备开机到出图的5个关键操作步骤
  • ArcGIS学习-19 实战-表面分析
  • 【算法】双指针(二)复写零
  • 视频串行解串器(SerDes)介绍
  • PyTorch 动态图的灵活性与实用技巧
  • 【P01_AI测试开发课程-导论】
  • 从社交破冰到学习规划,鸿蒙5开启智慧校园新生活
  • 【Linux操作系统】简学深悟启示录:文件fd
  • Kata Container 部署与应用实践
  • 【CentOS7】docker安装成功后测试,报Unable to find image ‘hello-world:latest‘ locally
  • springboot配置请求日志
  • 2-ATSAMV71Q21-BOOT
  • 【Qt开发】显示类控件(一)-> QLabel
  • 把不确定变成确定性收益:电力交易未来场景的预测、优化与实操
  • 大数据毕业设计选题推荐-基于大数据的国家药品采集药品数据可视化分析系统-Spark-Hadoop-Bigdata
  • 如何在Linux上使用Docker在本地部署开源PDF工具Stirling PDF:StirlingPDF+cpolar让专业操作像在线文档一样简单
  • 7,000 星!AutoMQ 开源再创里程碑
  • 四大金刚之计算机操作系统
  • 深入剖析 MyBatis 核心原理模块一:快速入门
  • 【Ansible】的介绍
  • VMware共享文件夹设置