Hystrix的熔断与降级
1.Hystrix断路器
1.1.分布式系统面临的问题
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”.
造成雪崩的原因可以归纳为以下三个:
服务提供者不可用(硬件故障,程序Bug,缓存击穿,用户大量请求)
重试加大流量(用户重试,代码逻辑重试)
服务调用者不可用(同步等待造成的资源耗尽)
最终的结果就是一个服务不可用,导致一系列服务的不可用,而往往这种后果是无法预料的。
1.2.Hystrix概述
Hystrix [hɪst’rɪks]的中文含义是豪猪,因其背上长满了刺而拥有自我保护能力。
Hystix,即熔断器。类似保险丝角色!
主页:https://github.com/Netflix/Hystrix/
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
1.3.熔断器的工作机制:
正常工作的情况下,客户端请求调用服务API接口:
当有服务出现异常时,直接进行失败回滚,服务降级处理:
当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。
这就好比去买鱼,平常超市买鱼会额外赠送杀鱼的服务。等到逢年过节,超时繁忙时,可能就不提供杀鱼服务了,这就是服务的降级。
系统特别繁忙时,一些次要服务暂时中断,优先保证主要服务的畅通,一切资源优先让给主要服务来使用,在双十一、618时,京东天猫都会采用这样的策略。
2.Hystrix服务降级
2.1.引入依赖
首先在user-consumer中引入Hystix依赖:
<!--服务熔断组件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.2.修改之前的Controller
在之前的Controller中添加熔断机制:
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
// 一旦调用服务方法失败,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public User get(@PathVariable("id") Long id) {
User u = this.userService.get(id);
return u;
}
//备选方案
public User processHystrix_Get(@PathVariable("id") Long id) {
//模拟的备选数据,可以来源于缓存
User u=new User();
u.setId(110);
u.setUsername("该ID:" + id + "没有没有对应的信息,null--@HystrixCommand");
u.setNote("no this database in MySQL");
return u;
}
2.3.修改主启动类
修改consumer并添加新注解@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscoveryClient // 开启EurekaClient功能
@EnableFeignClients // 开启Feign功能
@EnableCircuitBreaker//对hystrixR熔断机制的支持
public class SpringcloudDemoConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudDemoConsumerApplication.class, args);
}
}
2.4. 服务熔断测试
3个eureka先启动
主启动类SpringcloudDemoConsumerApplication
访问测试
关闭服务提供者
3. 服务降级优化-彻底解耦
修改microservicecloud-api工程,根据已经有的DeptClientService接口新建一个实现FallbackFactory接口的类DeptClientServiceFallbackFactory
@Component // 不要忘记添加
public class UserClientServiceFallbackFactory implements FallbackFactory<UserClientService> {
@Override
public UserClientService create(Throwable throwable) {
return new UserClientService() {
@Override
public List<User> queryUsers() {
return null;
}
@Override
public User get(Long id) {
User u=new User();
u.setId(110);
u.setUsername("该ID:\" + id + \"没有没有对应的信息,null--服务降级~~");
u.setNote("no this database in MySQL----服务降级!!!");
return u;
}
};
}
}
修改consumer工程,UserClientService接口在注解@FeignClient中添加fallbackFactory属性值
@FeignClient(value = "SPRINGCLOUD-DEMO-SERVICE",fallbackFactory=UserClientServiceFallbackFactory.class)
public interface UserClientService {
@RequestMapping("/all")
public List<User> queryUsers();
@RequestMapping("/get/{id}")
public User get(@PathVariable("id") Long id);
}
修改配置文件
开启服务熔断策略
feign.hystrix.enabled=true
4. 服务熔断
熔断在降级的基础之上
熔断其实是在降级的基础上引入了重试的机制。当某个时间内失败的次数达到了多少次就会触发熔断机制。熔断机制是应对雪崩效应的一种微服务链路保护机制。
断路器很好理解,当Hystrix Command请求后端服务熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,,断路器会切换到开路状态(Open)。这时所有请求会直接失败而不会发送到后端服务。 断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN)。这时会判断下一次请求的返回情况, 如果请求成功,断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN)。 Hystrix的断路器就像我们家庭电路中的保险丝,一旦后端服务不可用,断路器会直接切断请求链,避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力。
熔断器开关相互转换的逻辑图:
那么当断路器打开之后会发生什么呢?当熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,这个时候熔断器打开。打开之后,再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,返回fallback。通过断路器,实现了自动地发现错误并将主逻辑切换为降级逻辑,减少响应延迟的效果。
在断路器打开之后,处理逻辑并没有结束,我们的降级逻辑已经被成了主逻辑,那么原来的主逻辑要如何恢复呢?对于这一问题,hystrix也为我们实现了自动恢复功能。当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。
通过上面的一系列机制,hystrix的断路器实现了对依赖资源故障的端口、对降级策略的自动切换以及对主逻辑的自动恢复机制。这使得我们的微服务在依赖外部服务或资源的时候得到了非常好的保护,同时对于一些具备降级逻辑的业务需求可以实现自动化的切换与恢复,相比于设置开关由监控和运维来进行切换的传统实现方式显得更为智能和高效。
Hystrix可视化监控
1.概述
Hystrix提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。
Hystrix-dashboard 是一款针对 Hystrix 进行准实时监控的工具,通过 Hystrix Dashboard 我们可以在直观地看到各 Hystrix Command 的请求响应时间, 请求成功率等数据。
Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。
2.环境搭建步骤
在前面几节中的消费者中添加pom依赖。 我们需要添加Hystrix,Actuator和Hystrix-dashboard的依赖,具体如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- hystrix和 hystrix-dashboard相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
3.启动类设置
添加@EnableHystrixDashboard 开启Dashboard,如下
@SpringBootApplication
@EnableDiscoveryClient // 开启EurekaClient功能
@EnableFeignClients // 开启Feign功能
@EnableCircuitBreaker//对hystrixR熔断机制的支持
@EnableHystrixDashboard //开启仪表盘
public class SpringcloudFeignProdcutConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudFeignProdcutConsumerApplication.class, args);
}
}
4.注册HystrixMetricsStreamServlet
在2.x之前的版本中,会自动注入该Servlet的,但是在2.x之后的版本,没有自动注册该Servlet,所以这里需要我们手动的注册该Servlet到容器中,代码如下:
/**
* 配置Hystrix.stream的servlet
* @return
*/
@Bean
public ServletRegistrationBean registrationBean() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
访问http://localhost:80/hystrix 这里是你部署dashboard服务的地址和端口,会出现如下所示界面:
5.可视化监控
上面案例获取的监控数据是纯json数据,可读性不强,我们可以单独创建一个服务来做可视化监控。
然后启动服务,访问此地址:
http://localhost:80/hystrix
点击"Monitor Stream"进入监控页面
7.如何查看
-
7色
-
1圈 实心圆:
共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色<黄色<橙色<红色递减。 该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。 所以通过该实 心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例。
-
1线
曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。 面板每个指标所代表的意义: