一、初识Sentinel
1、雪崩问题及解决方案
1.1 雪崩问题
一个微服务故障宕机,其他微服务调用该宕机的微服务因此也会宕机,引起微服务连锁宕机的现象
- 超时处理
- 设定超时时间,请求超时则返回错误信息,不用无休止等待
- 舱壁模式
- 也叫线程隔离
- 限制每个业务使用的线程数
- 熔断降级
- 类似保险丝
- 由断路器统计业务执行的异常比例
- 超出阈值熔断该业务,拦截访问该业务的一切请求
- 流量控制
- 限制业务访问的QPS(Query Per Second)
总结
- 避免瞬间高并发流量导致服务故障
- 流量控制
避免因服务故障引起雪崩问题
默认情况下sentinel会监控SpringMVC的每一个端点
- SpringMVC的每一个端点就是调用链路中的一个资源
1、快速入门(略)
2、流控模式
三种流控模式
- 直接(默认模式)
- 统计当前资源的请求,触发阈值时对当前资源直接限流
- 关联
- 统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
- 高优先级资源触发阈值,对低优先级资源限流
- 链路
- 请求达到流控阈值时应该采取的措施
三种流控效果
- 快速失败(默认处理方式)
- 达到阈值后,新的请求会被立即拒绝并抛出FlowException异常
- QPS超过阈值时,拒绝新的请求
- warm up(预热模式)
- 对超出阈值的请求同样是拒绝并抛出异常
- 这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值
- QPS超过阈值时,拒绝新的请求;QPS阈值是逐渐提升的,可以避免冷启动时高并发导致服务宕机
- 举例
- 设置QPS的threshold为10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后在5秒后逐渐增长到10
- 排队等待
- 线程隔离
- 熔断降级
两者都是保护客户端(即微服务调用者)的
线程隔离的两种方式
- 线程池隔离
- 基于线程池模式
- 给每个微服务调用的业务分配一个线程池,利用线程池本身实现隔离效果
- 优点
- 隔离控制更强
- 基于线程池模式
- 信号量隔离(Sentinel默认使用)
- 基于计数器模式
- 不创建线程池,而是计数器模式
- 记录业务使用的线程数量,达到信号量上限时,禁止新的请求
- 优点
- 轻量级
- 适合高并发场景
- 基于计数器模式
线程隔离
- QPS
- 每秒的请求数
线程数
由断路器统计服务调用的异常比例、慢请求比例
- 如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求
- 而当服务恢复时,断路器会放行访问该服务的请求
断路器控制熔断和放行是通过状态机来完成
- 断路器状态
- 断路器Closed
- 请求正常
- 断路器关闭状态,放行所有请求,统计异常比例、慢请求比例
- 超过阈值则切换到Open状态
- 断路器Open
- 熔断降级
- 所有请求直接降级快速失败
- Open状态5秒后会进入Half-Open状态
- 断路器Half-Open
- 熔断时间结束,尝试放行请求
- 放行成功则关闭熔断器
- 放行失败则打开熔断器
- 熔断时间结束,尝试放行请求
- 断路器Closed
断路器三种熔断策略
- 慢调用
- 在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断
- 异常比例
- 统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常的比例达到设定的比例阈值(或超过指定异常数),则触发熔断
- 统计单位时长内异常调用的比例,超过阈值则熔断
- 异常数(跟异常比例雷同)
- 对调用方的来源做控制
授权规则两种方式
- 白名单
- 来源(origin)在白名单内的调用者允许访问
黑名单
原始模式(Sentinel的默认模式)
- 将规则保存在内存,重启服务会丢失
- pull模式
- 保存在本地文件或数据库,定时去读取
- push模式
- 是阿里巴巴开源的面向分布式服务架构的流量控制组件
以流量为切入点,从多个纬度维护微服务的稳定性
限制业务访问的QPS(每秒访问次数),避免因访问流量徒增导致微服务故障
限流规则
- 三种流控模式
- 线程池隔离
- 基于线程池模式
- 给每个微服务调用的业务分配一个线程池,利用线程池本身实现隔离效果
- 优点
- 隔离控制更强
- 基于线程池模式
- 信号量隔离(Sentinel默认使用)
- 由断路器统计服务调用的异常比例、慢请求比例
- 如果超出阈值则会熔断该服务
- 即拦截访问该服务的一切请求
- 当服务恢复时,断路器会放行访问该服务的请求
- 如果超出阈值则会熔断该服务
断路器控制熔断和放行是通过状态机来完成
- 断路器状态
修改微服务调用者的配置文件application.yml,开启Feign的Sentinel功能
feign:
sentinel:
enabled: true # 开启feign对sentinel的支持
给FeignClient编写失败后的降级逻辑
- 方式一:FallbackClass
- 无法对远程调用的异常做处理
方式二:FallbackFactory(推荐)
- 可以对远程调用的异常做处理
Feign模块编写类实现接口FallbackFactory
@Slf4j public class UserClientFallbackFactory implements FallbackFactory<UserClient> { @Override public UserClient create(Throwable throwable) { return new UserClient() { @Override public User findById(Long id) { log.error("查询用户异常", throwable); return new User(); } }; } }
将改FallbackFactory注册在Feign模块的Feign配置类中
public class DefaultFeignConfiguration { @Bean public UserClientFallBack userClientFallBack(){ return new UserClientFallBack(); } }
将FallbackFactory配置到FeignClient
```java @FeignClient(value = “userservice”, fallbackFactory = UserClientFallbackFactory.class) public interface UserClient {
@GetMapping(“/user/{id}”) User findById(@PathVariable(“id”) Long id); } ```
- 方式一:FallbackClass