上一节整理了Sentinel的限流,限流可以降低微服务的负载,避免因为高并发而故障,进而传递给其他相关服务而引发服务雪崩。以上仅为避免服务故障,而当某个服务真正故障时,如何处理才能防止服务雪崩? ⇒ Sentinel支持隔离和降级两种方案
采用线程隔离,即舱壁模式:
此时,服务C故障,最大损失10个线程,不会长期占用其他线程,如此,服务A到服务B仍可正常访问,阻止了故障的传递。
熔断降级,即当请求的失败比例超过阈值时,熔断器阻断服务A到服务D的请求,以后服务A到服务D的请求过来就会直接失败,它没压根机会去访问,也就不会导致资源耗尽,也就不会发生故障传递。
可以看到,不管是线程隔离还是熔断降级,都是对服务调用方的保护,别因为别的服务故障而拖垮自己。
SpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合Feign和Sentinel
feign:
sentinel:
enabled: true # 开启Feign的Sentinel功能
方式一:FallbackClass,不能对远程调用的异常做处理
方式二:FallbackFactory,可以对远程调用的异常做处理,常选这种
这是未处理前,feign处理的接口:
@FeignClient(value = "userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
@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();
}
};
}
}
public class DefaultFeignConfiguration {
//new个对象返回
@Bean
public UserClientFallbackFactory userClientFallbackFactory(){
return new UserClientFallbackFactory();
}
}
@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
到此,Feign整合Sentinel成功。也可再看下降级处理的效果(停掉被调用服务):
实现线程隔离有两种方式:
基于信号量即这个资源请求能用的线程就10个,有个计数器,用一个少一个,请求完后还回去,用完后面的请求就没得用了,以达到舱壁隔离的效果。
两种方式的优缺点:
需求:给 UserClient的查询用户接口设置流控规则,线程数不能超过 2
由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器才会放行访问该服务的请求。实现思路如下:
达到某个阈值时,触发熔断,这个就是断路器的熔断策略,分为这三种:慢调用、异常比例、异常数
慢调用:业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断。
关于慢调用,即正常蹲坑6分钟,你蹲一小时,半天不释放资源,自然会影响到其他请求。
- RT超过500ms的调用是慢调用
- 统计最近10000ms内的请求
- 如果请求量超过10次,并且慢调用比例不低于0.5,则触发熔断
- 熔断时长为5秒,然后进入half-open状态,放行一次请求做测试
接下来完成一个实际例子:
需求:
给 UserClient的查询用户接口设置降级规则,慢调用的RT阈值为50ms,统计时间为1秒,最小请求数量为5,失败阈值比例为0.4,熔断时长为5
为了触发慢调用规则,这里修改UserService中的业务,使用休眠来模拟慢调用:
开始演示:
一定时间内的请求,异常请求所占的比例达到设定的比例阈值,或者异常请求的数量达到了设定的数量阈值,即熔断。
此配置即统计最近1000ms内的请求,如果请求量超过10次,并且异常比例不低于0.4,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。
此配置即统计最近1000ms内的请求,如果请求量超过10次,并且异常数不低于2个,就触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。
需求:
给 UserClient的查询用户接口设置降级规则,统计时间为1秒,最小请求数量为5,失败阈值比例为0.4,熔断时长为5s
这里手动抛异常模拟异常的发生:
熔断策略小结: