一. Sentinel相关概念
1. 雪崩问题及解决
1.1 雪崩问题
一个微服务宕机,其他微服务调用该宕机微服务也会宕机,引起微服务连锁宕机的现象
微服务间调用错综复杂,一个微服务往往依赖于多个微服务
1.2 解决方案
- 超时处理
- 设定超时时间,请求超时则返回错误信息,不用无休止等待
- 仓壁模式(线程隔离)
- 限制每个业务使用的线程数
- 熔断降级
- 使用断路器统计业务执行的异常比例,超过阈值即熔断该业务,拦截访问该业务的一切请求
- 流量控制
- 限制业务访问的QPS
总结
- 避免高并发流量导致服务故障
- 流量控制
避免因服务宕机引起的雪崩问题
默认情况下Sentinel会监控SpringMVC的每一个端点
- SpringMVC的每一个端点就是调用链路中的一个资源
1.流控模式
- 直接(默认)
- 统计当前资源的请求,触发阈值时对当前资源直接限流
- 关联
- 统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
- 高优先级资源触发阈值,对低优先级资源限流
- 链路
三种流控效果
- 快速失败(默认)
- 达到阈值后,新的请求会被立即拒绝并抛出FlowException异常
- QPS超过阈值,拒绝新请求
- Warm Up(预热模式)
- 对超出阈值的请求拒绝并抛出异常
- 阈值动态变化,从较小值逐渐增大到最大阈值
- 可以避免冷启动时瞬间高并发导致服务宕机
- 排队等待
- 线程池隔离
- 基于线程池模式
- 给每个微服务调用的业务分配一个线程池,利用线程池本身实现隔离效果
- 优点
- 隔离控制更强
- 基于线程池模式
- 信号量隔离(Sentinel默认)
由断路器统计服务调用的异常比例,慢请求比例
- 如果超过阈值则会熔断该服务,即拦截访问该服务的一切请求
- 而当服务恢复时,熔断器会放行访问该服务的请求
断路器控制熔断和放行是通过状态机来完成
断路器状态
- 断路器closed
- 请求正常
- 断路器状态关闭,放行所有请求,统计异常比例,慢请求比例
- 超过阈值则切换到OPEN状态
- 断路器Open
- 所有请求直接降级快速失败
- open状态5秒后会进入half-open
- 断路器half-open
- 熔断时间结束,尝试放行一个请求
- 放行成功则关闭断路器
- 放行失败则打开断路器
断路器三种熔断策略
- 熔断时间结束,尝试放行一个请求
- 断路器closed
- 慢调用
- 在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断
- 异常比例
- 统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常比例达到设定的比例阈值,则触发熔断
- 异常数
授权规则的两种方式
- 白名单
- 来源(origin)在白名单内的调用者允许访问
黑名单
原始模式(Sentinel默认)
- 将规则保存在内存,重启服务会丢失
- pull模式
- 保存在本地或数据库,定时读取
push模式
修改application.yml,开启feign的Sentinel功能
feign:
sentinel:
enable: true
给FeignClient编写调用失败后的降级逻辑
- 方式一: FallbackClass
- 无法对远程调用的异常做处理
方式二: FallbackFactory(推荐)
- 可以对远程调用的异常做处理
- 编写FallbackFactory逻辑
```java
@Component
@Slf4j
public class ArticleFeignFallback implements FallbackFactory
{
@Override public ArticleFeign create(Throwable throwable) { return new ArticleFeign() {
@Override
public ResponseResult<ApAuthor> findByUserId(Integer userId) {
log.error("参数:{}", userId);
log.error("文章 findByUserId接口 远程调用失败:{}", throwable.getMessage());
return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
}
} } }
2. FeignClient注解添加fallbackFactory
```java
@FeignClient(value = "leadnews-article",
fallbackFactory = ArticleFeignFallback.class)
public interface ArticleFeign {
@GetMapping("/api/v1/author/findByUserId/{userId}")
ResponseResult<ApAuthor> findByUserId(@PathVariable("userId") Integer userId);
- Feign配置类添加ComponentScan注解扫描FeignFallbackFactory
@EnableFeignClients(basePackages = "com.heima.feigns",defaultConfiguration = HeimaFeignAutoConfiguration.class)
@Configuration
@ComponentScan("com.heima.feigns.fallback")
public class HeimaFeignAutoConfiguration {
@Bean
Logger.Level level() {
return Logger.Level.FULL;
}
}
- 方式一: FallbackClass