一、问题引入
如果服务提供者响应非常缓慢,那么消费者对提供者的请求就会被强制等待,直到提供者响应或超时。在高负载场景下,如果不作任何处理,此类问题可能会导致服务消费者的资源耗尽甚至整个系统的崩溃。
1.1、雪崩效应
微服务架构的应用系统通常包含多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,微服务之间难免存在依赖关系。任何微服务都并非100%可用,网络往往也很脆弱,因此难免有些请求会失败。
我们通常把“基础服务故障”导致“级联故障”的现象称为雪崩效应。雪崩效应描述的是提供者不可用导致消费者不可用,并将不可用逐渐放大的过程。
1.2、如何容错
要想防止雪崩效应,必须有一个强大的容错机制。该容错机制需要实现以下两点:
a、为网络请求设置超时:为每个网络请求设置超时,让资源尽快释放。
b、使用断路器模式
我们可通过以上两点机制保护应用,从而防止雪崩效应并提升应用的可用性。
1.3、断路器模式简介
断路器可理解为对容易导致错误的操作的代理。这种代理能够统计一段时间内调用失败的次数,并决定是正常请求依赖的服务还是直接返回。
断路器可以实现快速失败,如果它在一段时间内检测到许多类似的错误(例如超时),就会在之后的一段时间内,强迫对改服务的调用快速失败,即不再请求所依赖的服务。这样应用程序就无须再浪费CPU时间去等待长时间的超时。
断路器也可自动诊断依赖的服务是否已经恢复正常,如果发现依赖的服务已经恢复正常,那么就会恢复请求该服务,使用这种方式,就可以实现微服务的“自我修复”。
当依赖的服务不正常时打开断路器时快速失败,从而防止雪崩效应;当发现依赖的服务恢复正常时,又会恢复请求。
断路器状态转换图,如下:
说明:
1、正常情况下,断路器关闭,可正常请求依赖的服务。
2、当一段时间内,请求失败率达到一定阔值(如错误率达到50%,或100次/分钟等),断路器就会打开。此时,不会再去请求依赖的服务。
3、断路器打开一段时间后,会自动进入“半开”状态。此时,断路器可允许一个请求访问依赖的服务。如果该请求能够成功调用,则关闭断路器;否则继续保持打开状态。
二、Hystrix简介
hystrix是一个实现了超时机制和断路器模式的工具类库。
2.1、简介
hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务、或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
hystrix主要通过以下几点实现容错和延迟:
包裹请求
使用hystrixCommand(或hystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用到了设计模式中的“命令模式”。
跳闸机制
当某服务的错误率超过一定阔值时,hystrix可以自动或手动跳闸,停止请求该服务一段时间。
资料隔离
hystrix为每个依赖都维护了一个小型的线程池(或信号量)。如果该线程池已满,发往该依赖的请求就会被立即拒绝,而不是排队等待,从而加速失败判定。
监控
hystrix可以近乎实时的监控运行指标和配置的变化,例如成功、失败、超时以及被拒绝的请求等
回退机制
当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
自我修复
断路器打开一段时间后,会自动进入“半开”状态。
三、使用hystrix实现容错
3.1、通用方式整合Hystris
复制工程spring-ribbon-eureka-client,改名为spring-hystrix-consumer
3.1.1、添加依赖
org.springframework.cloud
spring-cloud-starter-hystrix
3.1.2、在启动类上加上注解@EnableHystrixpackage com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableHystrix
@EnableEurekaClient
@SpringBootApplication
public class SpringHystrixConsumerApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static voi