• 微服务雪崩问题:
    • 微服务中,服务间的关系错综复杂,一个服务往往依赖多个其他服务,一个服务出现了问题,导致依赖他的微服务tomcat线程得不到释放,服务器支持的线程和并发数优先,越来越多的请求堆积,导致微服务资源耗尽而瘫痪,从而导致更多的微服务出问题, ,这就是雪崩问题
  • 解决雪崩问题的常见四种方法,:
    • 超时处理:设定超时时间,请求超过一定的时间,没有响应就返回错误信息,不会无休止的等待
    • 仓壁模式:线程隔离
    • 断路器(熔断):由断路器统计某个业务执行的异常比例,如果超出阈值则会熔断业务,拦截访问改业务的一直访问
    • 限流:现在业务的访问的QPS,避免服务因流量的突增而故障
  • 服务保护对比: | | Sentinel | Hystrix | | —- | —- | —- | | 隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 | | 熔断降级策略 | 基于慢调用比例或异常比例 | 基于失败比率 | | 实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) | | 规则配置 | 支持多种数据源 | 支持多种数据源 | | 扩展性 | 多个扩展点 | 插件的形式 | | 基于注解的支持 | 支持 | 支持 | | 限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | | 流量整形 | 支持慢启动、匀速排队模式 | 不支持 | | 系统自适应保护 | 支持 | 不支持 | | 控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 | | 常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |

  • 微服务整合sentinel

    • 导入依赖

      1. <!--sentinel-->
      2. <dependency>
      3. <groupId>com.alibaba.cloud</groupId>
      4. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
      5. </dependency>
    • 修改application.yaml文件,添加下面内容:

      server:
      port: 8088
      spring:
      cloud: 
      sentinel:
      transport:
      dashboard: localhost:8080
      
  • 流量控制:

    • 蔟点链路,:dispatcherservlet-service,mapoper就是一条蔟点链路,
    • 默认情况下;sentinel会监控 springmvc的每一个端点:就是每一个controller的接口
    • 流控和熔断都是对针对族点链路中的端点来设置,因此我们可以点击对应资源后面的按钮来设置规则:
      • 流控:流量控制
      • 降级:降级熔断
      • 热点:热点参数限流,是限流的一种
      • 授权:请求的权限控制
    • 流控模式:
      • 直接:统计当前资源的请求,触发阈值时对当前资源的限流,也是默认的设置
      • 关联:统计与当前资源关联的另一个资源,到达阈值时对当前资源限流
      • 链路:统计从指定链路访问到本资源的请求,触达阈值时;对指定的链路限流
    • 流控效果:
      • 快速失败:到达阈值时:新的请求会被立即拒绝并抛出FlowException异常,是默认的处理
      • wram up:预热模式,对超出阈值的请求同样是拒绝抛出异常,但是这种模式的阈值时动态变化的,随时间的变化才会到达指定的阈值;
      • 排队等待:当请求超过QPS阈值时,快速失败和warm up 会拒绝新的请求并抛出异常。
      • 而排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后
      • 来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。
    • 热点参数限流:
      • 之前的限流是统计访问某个资源的所有请求,判断是否超过QPS阈值。而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。

        2.4.4.案例

        案例需求:给/order/{orderId}这个资源添加热点参数限流,规则如下:
        •默认的热点参数规则是每1秒请求量不超过2
        •给102这个参数设置例外:每1秒请求量不超过4
        •给103这个参数设置例外:每1秒请求量不超过10
  • 隔离和降级:

    • Feign整合sentinel
    • 作用 业务失败的时候 不可以直接报错,而是应该返回一个友好的结果,这个就是失败降级逻辑
    • 2种方式:fallbackclass,无法对远程调用的异常处理
      fallbackfactory,可以对远程调用的异常做处理 ```java package cn.itcast.feign.clients.fallback;

import cn.itcast.feign.clients.UserClient; import cn.itcast.feign.pojo.User; import feign.hystrix.FallbackFactory; import lombok.extern.slf4j.Slf4j; 步骤一:在feing-api项目中定义类,实现FallbackFactory:

//泛型是fenign @Slf4j public class UserClientFallbackFactory implements FallbackFactory { @Override public UserClient create(Throwable throwable) { return new UserClient() { @Override public User findById(Long id) { log.error(“查询用户异常”, throwable); return new User(); } }; } }

步骤二:在feing-api项目中的DefaultFeignConfiguration类中将UserClientFallbackFactory注册为一个Bean: @Bean public UserClientFallbackFactory userClientFallbackFactory(){ return new UserClientFallbackFactory(); }

import cn.itcast.feign.clients.fallback.UserClientFallbackFactory; import cn.itcast.feign.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable;

步骤三:在feing-api项目中的UserClient接口中使用UserClientFallbackFactory: @FeignClient(value = “userservice”, fallbackFactory = UserClientFallbackFactory.class) public interface UserClient {

@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);

} ```

  • 线程隔离有2中实现方式:
    • 线程池隔离:给每个服务分配一个线池,;利用线程池本身实现隔离
    • 信号量隔离 :不创建线程池,使用计数器实现,记录访问的线程数量 达到上限时,不接受其他的请求
  • sentinel的规则默认是存储到内存中 关机重启就会消失;所以需要持久化

    • 原始模式:Sentinel的默认模式,将规则保存在内存,重启服务会丢失。
    • pull模式:控制台将配置的规则推送到Sentinel客户端,而客户端会将配置规则保存在本地文件或数据库中。以后会定时去本地文件或数据库中查询,更新本地规则。

    • push模式:控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配置变更的推送消息,完成本地配置更新。