SpringCloud学习—— Hystrix 断路器
Posted Johnny*
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud学习—— Hystrix 断路器相关的知识,希望对你有一定的参考价值。
Hystrix
前言
分布式系统面临的问题:
多个微服务之间调用时,如果扇出的链路上某个微服务的调用时间过长或者不可用,对于这个微服务的调用就会占用越来越多的系统资源,导致系统发生更多的级联故障,进而引起系统崩溃,发生所谓的“雪崩效应”。
因此需要对故障和延迟进行管理和隔离,以便当个依赖关系的失败,不会影响整个应用程序或 系统。这也是Hystrix的来源。
什么是Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败(如超时、异常等)。 Hystrix能够保证在 一个依赖出问题的情况下,不会导致整个服务事变、避免级联故障,以便提高分布式系统的弹性。
Hystrix的做法是: 当某个单元发生故障之后,通过断路器的故障监控,向调用方法返回一个符合预期的、可处理的备选方案,而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间的占用,从而避免了故障在 分布式系统的蔓延,内置雪崩。
一些概念
服务降级
服务器忙,请稍后再试,不让客户端等待并返回一个友好提示fallback
哪些情况会 发生降级
- 程序运行异常
- 超时
- 服务熔断触发服务降级
- 线程池/信号量打满也会导致服务降级
服务熔断
达到最大服务访问后,直接拒绝访问,然后调用服务降级方法并返回友好 提示。相当于保险丝,在家用电器超负荷时,拉闸限电。
服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。
代码演示
模拟故障
使用jemeter发起200万个请求http://localhost:8001/payment/hystrix/timeout/35
1个请求http://localhost:8001/payment/hystrix/ok/35,会发现后者也会 被滞缓。
原因是:
SpringBoot集成tomcat,而tomcat默认的工作线程被打满了,没有多余的线程来分解压力和处理 。因为有上述故障或不佳表现,才有了我们的降级/容错/限流等技术的诞生。
解决思路
- 对于超时 导致服务器变慢(访问转圈)应该设置超时不再等待
- 出错(宕机 或程序运行错误),出错要有兜底
解决方案:
服务提供方(8001)超时了,调用者(80) 不能一直卡死等待,必须要有服务降级
服务提供方(8001)宕机了,调用者(80)不能一直卡死等待,必须要有服务降级。
服务提供方(8001)OK,调用者(80)自己出故障或有自我要求(自己等待时间小于服务提供方的业务所需时间),自己降级处理。
服务降级
8001demo
引入Hystrix依赖spring-cloud-starter-netflix-hystrix
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
主启动类加入注解@EnableCircuitBreaker,服务降级
Service层
@HystrixCommand(fallbackMethod = "兜底的方法",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
})
eureka自带负载均衡ribbon
配置过的热部署方式对Java代码的改动明显有效,但对于@HystrixCommand内属性的修改建议重启微服务。
服务降级客户端和服务端都可以设置,但是一般放置在客户端
客户端处配置服务降级
application.yaml文件
feign:
hystrix:
enabled: true
主启动类增加@EnableHystrix注解、@EnableFeignClients注解
超时设置:
@HystrixProperty注入的超时时间和application.yml注入的超时时间都处于生效状态, 哪边的时间小超时时间就取哪边. 当application.yml 未设置Hystrix的超时时间时, 会有个默认的超时时间1秒, 设置了application.yml的Hystrix超时时间后会覆盖掉1秒超时的默认设置.
Feign的超时时间为:Hystrix + Ribbon的
Ribbon 的超时时间(ReadTimeOut + ConnectionTimeOut)
关于客户端feign readTimeout设置
存在的问题:
- 每个方法都要配置一个fallbackMethod的代码膨胀问题 —— 全局服务降级解决
- 异常处理 代码与业务逻辑混在一起的耦合问题。 —— 服务类实现接口
全局服务降级
- 在需要使用服务降级的方法上加上@HystrixCommand注解
- 在Controller上加上@DefaultProperties(defaultFallback = “全局降级方法”)
- 定义全局降级方法
package com.johnny.springcloud.controller;
import com.johnny.springcloud.service.PaymentService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Johnny Lin
* @date 2021/6/25 14:45
*/
@RestController
@Slf4j
@RequestMapping("consumer/payment")
@DefaultProperties(defaultFallback = "globalFallback_Method") //开启全局fallback
public class OrderController {
@Autowired
private PaymentService paymentService;
@GetMapping("/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
return paymentService.paymentInfo_OK(id);
}
//hystrix.command.serverMethod.execution.isolation.thread.timeoutInMilliseconds=3000
@GetMapping("/hystrix/timeout/{id}")
// @HystrixCommand(fallbackMethod = "paymentTimeoutFallbackMethod",commandProperties =
// {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="30000") } )
@HystrixCommand
public String paymentInfo_Timeout(@PathVariable("id") Integer id){
int a = 25 / 0; //处理异常
return paymentService.paymentInfo_Timeout(id);
}
public String paymentTimeoutFallbackMethod(@PathVariable("id") Integer id){
return "消费者端80, 支付系统繁忙请10秒钟之后再试或者自己运行出错请检查自己 2222 o(╥﹏╥)o";
}
//不是globalFallback_Method(@PathVariable("id") Integer id)
public String globalFallback_Method(){
return "全局服务降级处理方法 globalFallback_Method";
}
}
解决代码耦合问题
80客户端:
PaymentService 接口
package com.johnny.springcloud.service;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @author Johnny Lin
* @date 2021/6/25 14:26
*/
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackService.class) //要调用的服务端名称
public interface PaymentService {
@GetMapping("payment/hystrix/ok/{id}")
String paymentInfo_OK(@PathVariable("id") Integer id);
@GetMapping("payment/hystrix/timeout/{id}")
String paymentInfo_Timeout(@PathVariable("id") Integer id);
}
package com.johnny.springcloud.service;
import org.springframework.stereotype.Component;
/**
* @author Johnny Lin
* @date 2021/6/26 10:23
*/
//还要加上component注解
@Component
public class PaymentFallbackService implements PaymentService {
@Override
public String paymentInfo_OK(Integer id) {
return "paymentInfo_OK invoke o(╥﹏╥)o ~~";
}
@Override
public String paymentInfo_Timeout(Integer id) {
return "paymentInfo_Timeout invoke o(╥﹏╥)o ~~";
}
}
关闭服务端8001,启动80访问
http://localhost/consumer/payment/hystrix/timeout/99
结果:
实现类是针对异常情况(服务器宕机、超时、运行时异常)的fallback处理,是客户端的降级方案。
接口才是服务端的映射,对应服务端的具体逻辑业务。
熔断
熔断机制
熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者 响应时间过长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路。
熔断类型
熔断打开: 请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态
熔断关闭: 熔断关闭不会对服务进行熔断
熔断半开: 部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断。
断路器在什么情况下起作用
断路器打开之后
Hystrix的工作流程
Hystrix Dashboard
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会 持续地记录所有通过Hystrix发起的请求执行信息,并以统计报表和图形的形式展示给用户。
pom.xml引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
主启动类增加注解
@EnableHystrixDashboard
以上是关于SpringCloud学习—— Hystrix 断路器的主要内容,如果未能解决你的问题,请参考以下文章
spring cloud: Hystrix:feign类似于hystrix的断容器功能
SpringCloud学习总结——服务熔断Hystrix高级