Sentinel的线程隔离和熔断降级

上一节整理了Sentinel的限流,限流可以降低微服务的负载,避免因为高并发而故障,进而传递给其他相关服务而引发服务雪崩。以上仅为避免服务故障,而当某个服务真正故障时,如何处理才能防止服务雪崩? ⇒ Sentinel支持隔离和降级两种方案

文章目录

  • 1、线程隔离和熔断降级
  • 2、Feign整合Sentinel
  • 3、FallbackFactory代码逻辑
  • 4、线程隔离
  • 5、Sentinel熔断的实现原理
  • 6、熔断策略--慢调用
  • 7、熔断策略--异常比例、异常数

1、线程隔离和熔断降级

采用线程隔离,即舱壁模式:

Sentinel的线程隔离和熔断降级_第1张图片

  • 业务1:服务A到服务B,限制10线程数
  • 业务2:服务A到服务C,限制10线程数

此时,服务C故障,最大损失10个线程,不会长期占用其他线程,如此,服务A到服务B仍可正常访问,阻止了故障的传递。

Sentinel的线程隔离和熔断降级_第2张图片

熔断降级,即当请求的失败比例超过阈值时,熔断器阻断服务A到服务D的请求,以后服务A到服务D的请求过来就会直接失败,它没压根机会去访问,也就不会导致资源耗尽,也就不会发生故障传递。

可以看到,不管是线程隔离还是熔断降级,都是对服务调用方的保护,别因为别的服务故障而拖垮自己。

2、Feign整合Sentinel

SpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合Feign和Sentinel

  • 修改服务调用方的application.yaml文件,开启Feign的Sentinel功能
feign:
  sentinel:    
  	enabled: true # 开启Feign的Sentinel功能

  • 给FeignClient编写失败后的降级逻辑(被阻断了,走另一条路,比如返回msg调用xxService失败)
方式一:FallbackClass,不能对远程调用的异常做处理
方式二:FallbackFactory,可以对远程调用的异常做处理,常选这种

3、FallbackFactory代码逻辑

这是未处理前,feign处理的接口:

@FeignClient(value = "userservice")
public interface UserClient {

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
  • 在feing-api项目中定义类,实现FallbackFactory接口,且FallbackFactory的泛型中即为关联接口的类型
@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {   //泛型中指定关联的接口的类型
    @Override
    public UserClient create(Throwable throwable) {
    	// 创建UserClient接口实现类(匿名内部类),实现其中的方法,编写失败降级的处理逻辑
        return new UserClient() {
            @Override
            public User findById(Long id) {
            	// 记录异常信息
                log.error("查询用户异常", throwable);
                // 根据业务需求返回默认的数据,这里是空用户
                return new User();
            }
        };
    }
}


  • 在模块的配置类DefaultFeignConfiguration中将UserClientFallbackFactory注册为一个Bean:
public class DefaultFeignConfiguration {

	//new个对象返回
    @Bean
    public UserClientFallbackFactory userClientFallbackFactory(){
        return new UserClientFallbackFactory();
    }
}
  • 在feing-api项目中的UserClient接口中用fallbackFactory属性,使用UserClientFallbackFactory
@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
  • 重启服务,在Sentinel簇点链路中可以看到被远程调用的服务

Sentinel的线程隔离和熔断降级_第3张图片

到此,Feign整合Sentinel成功。也可再看下降级处理的效果(停掉被调用服务):

在这里插入图片描述
Sentinel的线程隔离和熔断降级_第4张图片

4、线程隔离

实现线程隔离有两种方式:

  • 线程池隔离
  • 信号量隔离(Sentinel默认采用)

基于信号量即这个资源请求能用的线程就10个,有个计数器,用一个少一个,请求完后还回去,用完后面的请求就没得用了,以达到舱壁隔离的效果。
Sentinel的线程隔离和熔断降级_第5张图片

两种方式的优缺点:

  • 基于计数器模式,简单,开销小
  • 基于线程池模式,有额外开销,但隔离控制更强

Sentinel的线程隔离和熔断降级_第6张图片
Sentinel中的配置示例如下:

Sentinel的线程隔离和熔断降级_第7张图片

  • QPS:就是每秒的请求数
  • 线程数:是该资源能使用用的tomcat线程数的最大值。也就是通过限制线程数量,实现舱壁模式
需求:给 UserClient的查询用户接口设置流控规则,线程数不能超过 2
  • Sentinel中添加流控规则,阈值类型选择线程数

Sentinel的线程隔离和熔断降级_第8张图片

  • 启动Jmeter,对/order/101发起测试

Sentinel的线程隔离和熔断降级_第9张图片

  • 查看结果数,10个请求,8个返回结果user为null且控制台输出报错日志(请求不会失败,因为上面已经做了降级的逻辑处理)

Sentinel的线程隔离和熔断降级_第10张图片

5、Sentinel熔断的实现原理

由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器才会放行访问该服务的请求。实现思路如下:

Sentinel的线程隔离和熔断降级_第11张图片

  • 断路器处于closed时,一切请求都不被拦截,且会被统计异常和慢的比例
  • 当比例达到失败阈值,断路器open,所有请求一过来就快速失败
  • 当熔断时间结束,切换好半开放状态,即Half-Open
  • Half-Open状态会尝试放行一些请求,如果依旧失败,则回到Open状态继续拦截,如果成功,则回到Closed状态

6、熔断策略–慢调用

达到某个阈值时,触发熔断,这个就是断路器的熔断策略,分为这三种:慢调用、异常比例、异常数

慢调用:业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断。

关于慢调用,即正常蹲坑6分钟,你蹲一小时,半天不释放资源,自然会影响到其他请求。

Sentinel的线程隔离和熔断降级_第12张图片
以上这个Sentinel配置,即:

- RT超过500ms的调用是慢调用
- 统计最近10000ms内的请求
- 如果请求量超过10次,并且慢调用比例不低于0.5,则触发熔断
- 熔断时长为5秒,然后进入half-open状态,放行一次请求做测试

接下来完成一个实际例子:

需求:
给 UserClient的查询用户接口设置降级规则,慢调用的RT阈值为50ms,统计时间为1秒,最小请求数量为5,失败阈值比例为0.4,熔断时长为5

为了触发慢调用规则,这里修改UserService中的业务,使用休眠来模拟慢调用:

Sentinel的线程隔离和熔断降级_第13张图片

开始演示:
  • 配置Sentinel降级规则

Sentinel的线程隔离和熔断降级_第14张图片

  • 狂刷/order/101接口(或者Ctrl+R),/order/101调用的user id就是1,即可触发熔断

Sentinel的线程隔离和熔断降级_第15张图片

  • 此时访问其他用户,也返回空,因为阻断器open,直接挡回去了

Sentinel的线程隔离和熔断降级_第16张图片

  • 估摸着5s过去了,阻断器进入到了Half-Open,再重新请求,可以看到正常返回了,当然此时熔断器变为Closed状态

Sentinel的线程隔离和熔断降级_第17张图片

7、熔断策略–异常比例、异常数

一定时间内的请求,异常请求所占的比例达到设定的比例阈值,或者异常请求的数量达到了设定的数量阈值,即熔断。

Sentinel的线程隔离和熔断降级_第18张图片
此配置即统计最近1000ms内的请求,如果请求量超过10次,并且异常比例不低于0.4,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。


Sentinel的线程隔离和熔断降级_第19张图片
此配置即统计最近1000ms内的请求,如果请求量超过10次,并且异常数不低于2个,就触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。

需求:
给 UserClient的查询用户接口设置降级规则,统计时间为1秒,最小请求数量为5,失败阈值比例为0.4,熔断时长为5s

这里手动抛异常模拟异常的发生:

Sentinel的线程隔离和熔断降级_第20张图片

  • 配置降级规则

Sentinel的线程隔离和熔断降级_第21张图片

  • 刷/order/102,查uid为2的用户,达到异常比例来触发熔断

Sentinel的线程隔离和熔断降级_第22张图片

  • 然后再访问/order/103,此时103立即失败(被阻断了,所以耗时极小,这里只有7ms)

Sentinel的线程隔离和熔断降级_第23张图片

  • 等过了阻断器open的时间,再访问就正常了

Sentinel的线程隔离和熔断降级_第24张图片

熔断策略小结:

Sentinel的线程隔离和熔断降级_第25张图片

你可能感兴趣的:(SpringCloud,sentinel,微服务,流量控制,熔断,线程隔离)