微服务保护——隔离和降级
关于服务隔离和降级的概念,入门理解,见(一)微服务保护——Sentinel
使用Sentinel限流可以降低服务的负载,从而避免服务因为过高并发而出现故障,服务不出现故障就不会把故障传递给其他服务,也就不会出现雪崩现象。
所以限流是对服务故障的一种预防措施,但是对于已经出现故障的服务,就很容易把故障传递给依赖它的服务,这样就很容易产生雪崩。所以就需要使用线程隔离,降级熔断来避免雪崩。
一、FeignClient整合Sentinel:
步骤一:在feing-api项目中定义类,实现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();
}
};
}}
步骤二:在feing-api项目中的DefaultFeignConfiguration类中将UserClientFallbackFactory注册为一个Bean:
@Bean
public UserClientFallbackFactory userClientFallback(){
return new UserClientFallbackFactory();
}
步骤三:在feing-api项目中的UserClient接口中使用UserClientFallbackFactory:
@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
二、线程隔离:
1、线程池隔离:
服务I依赖于服务AB,当请求进来的时候,会先创建两个线程池,然后依赖A的请求就从A的线程池获取一个线程访问服务A,依赖B的请求就从B的线程池获取一个线程访问服务B,这就实现了线程隔离。
当服务A发生故障,则最多也是把服务A的线程池的资源耗尽,不会让服务I的整个资源耗尽。
2、信号量隔离(Sentinel默认使用)
不用创建新的线程池,而是使用计数器监听信号量,每一个请求进来信号量就减去1。
3、两者的对比:
三、熔断降级:
1、认识:
熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。
即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。
2、熔断策略:
2.1 慢调用:
慢调用:业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断。例如:
解读:RT超过500ms的调用是慢调用,统计最近10000ms内的请求,如果请求量超过10次,并且慢调用比例不低于0.5,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。