开发者

SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

开发者 https://www.devze.com 2025-05-10 10:20 出处:网络 作者: 昊坤说不出的梦
目录开发环境为什么要保护Sentinel 实现保护策略1:请求限流策略2:线程隔离策略3:服务熔断Sentinel 流量控制Sentinel 服务熔断总结开发环境
目录
  • 开发环境
  • 为什么要保护
  • Sentinel 实现保护
    • 策略1:请求限流
    • 策略2:线程隔离
    • 策略3:服务熔断
  • Sentinel 流量控制
    • Sentinel 服务熔断
      • 总结

        开发环境

        环境:Java 11、mysql 8.0、OpenFeign、sentinel-dashboard 1.8.6

        为什么要保护

        微服务在远程调用时,可能存在以下问题:

        1. 业务健壮性:

        如,购物车服务、商品服务之间互相调用,当一方挂掉,需要做兜底处理从而优化用户体验

        假设,查询购物车接口需要调用商品服务,商品服务挂了导致查询失败,但从业务角度为了提高用户体验,即使查询失败,购物车列表也应该展示出来(展示空数据/缓存数据)。而不是丢给用户一堆报错信息

        2. 级联失败(雪崩问题):

        如,高峰期时查询接口并发高,其他接口并发小;由于高并发接口占用过多的Tomcat连接,可能导致所有接口都延迟变高、长时间阻塞甚至失败。

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        以此类推,当互相调用的服务间出现问题时,可能导致整个集群都不可用

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        Sentinel 实现保护

        提示:这里可以添加要学的内容

        例如:

        1. 搭建 Java 开发环境
        2. 掌握 Java 基本语法
        3. 掌握条件语句
        4. 掌握循环语句

        策略1:请求限流

        理解:限制/控制接口的请求流量

        并发太高是导致服务故障的重要原因。

        因此通过限制或控制接口的并发流量,避免服务因流量激增而出现故障。

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        策略2:线程隔离

        理解:提前分配好资源(线程)给业务接口

        当一个业务接口响应时间长,而且并发高时,就可能耗尽服务器的线程资源,导致服务内的其它接口受到影响。

        因此为了降低/减小这种影响,使用线程隔离,其思想参考舱壁模型

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        如,查询接口访问频繁,会无休止地占用更多的线程资源,而导致其他业务的线程资源紧张或无法分配。

        线程隔离:锁死查询接口20线程,其他业务10线程,就算查询接口并发再高,只给20线程资源去调用,确保了其他业务不被影响。

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        策略3:服务熔断

        理解:对故障/速度慢的接口进行暂时切断,并提供一个友好提示以优化用户体验

        服务熔断主要有两点:

        • 编写服务降级逻辑:调用失败后的处理逻辑,可抛出异常/友好提示/默认数据/缓存数据。
        • 异常统计和熔断:统计异常比例,当比例过高表明该接口会影响到其它服务,应该拒绝调用该接口,而是直接走降级逻辑。

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        Sentinel 流量控编程制

        Sentinel 主要有两部分

        • 核心库(Jar包):直接引入到pom.XML就生效,在项目中可以编程式编写限流、隔离、熔断等规则。
        • 控制台(DashBoard):负责管理推送规则、监控、管理机器信息等。

        依赖引入:

         <dependency>
           <groupId>com.alibaba.cloud<javascript;/groupId>
           <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
           <version>2021.0.4.0</version>
         </dependency>

        控制台启动:

        下载:控制台jar包

        启动:java -Dserver.port=8090 -Dcsp.sentinel.dashphpboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

        配置application.yaml

        spring:
          cloud:
            sentinel:
              transport:
                dashboard: localhost:8090
              http-method-specify: true # 开启请求方式前缀(为了区分GET/POST/DELETE等请求)

        配置策略

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        SpringCloud Sentinel服务保护详解(请求限流、线程隔离、服务熔断)

        细节1:需要触发一次请求才会在Sentinel面板看到该接口的簇点

        细节2:默认直接在面板上的配置是临时的,重启服务后配置就清空了

        具体的流控规则需要根据业务来进行设置

        Sentinel 服务熔断

        问题1:当接口触发Sentinel配置的流控规则时,抛出异常,用户体验不佳

        解决方案:降级处理,展示空数据/缓存的旧数据

        问题2:当A接口需要远程调用B,而B延迟较高,拖慢了A的服务,用户体验差

        解决方案:熔断慢接口,直接停止使用B接口,走降级逻辑

        本次练习采用的是OpenFeign远程调用,使用远程调用主要有两种方式

        1. 方式一:FallbackClass,无法对远程调用的异常做处理
        2. 方式二:FallbackFactory,可以对远程调用的异常做处理,我们一般选择这种方式。

        故使用更为灵活的FallbackFactory

        首先配置降级逻辑:返回空集合

        @Slf4j
        public class ItemClientFallback implements FallbackFactory<ItemClient> {
            @Override
            public ItemClient create(Throwable cause) {
                return new ItemClient() {
                    @Override
                    public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
                        log.error("远程调用ItemClient#queryItemByIds方法出现异常,参数:{}", ids, cause);
                 javascript       // 查询购物车允许失败,查询失败,返回空集合
                        return CollUtils.emptyList();
                    }
        
                    @Override
          android          public void deductStock(List<OrderDetailDTO> items) {
                        log.error("扣减商品库存失败!",cause);
                        // 库存扣减业务需要触发事务回滚,查询失败,抛出异常
                        throw new BizIllegalException(cause);
                    }
                };
            }
        }

        将降级处理逻辑注册成@Bean

         /**
         * Feign配置类
         */
        public class DefaultFeignConfig {
            @Bean
            public ItemClientFallback itemClientFallback(){
                return new ItemClientFallback();
            }
        }

        在远程调用的注解处配置:失败处理逻辑的类

        /**
         * 远程调用商品服务
         */
        @FeignClient(value = "item-service",fallbackFactory = ItemClientFallback.class)
        public interface ItemClient {
        ...
        }

        总结

        以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号