SpringCloud中Hystrix之服务熔断
1. 什么是服务熔断
- 熔断器,也可称为断路器。
- 原理:
- 简单说,与日常生活中的电路工作原理相似。若电路发生短路现象,路保会立刻跳闸,防止发生不可避免的后果。
- 在分布式系统或应用中使用服务熔断后,对于整个应用中的服务调用可以自行判断服务的运行状态,或慢,或异常,或超时……此时,会主动熔断,(简单说就是紧急隔断联系)防止整个应用崩掉。
- 与日常中电路故障不同的是,加用电路故障解决后,需要手动送闸。而Hystrix则实现了弹性容错。也就是说,当服务状态稳定后,会尝试重联,一旦确定真正稳定了,则会真正重联。
1.1 服务熔断状态简介
- 熔断有3个状态,分别是:
- closed:
- 关闭状态。所有状态正常访问。
- open:
- 打开状态。此状态下,表明服务链接出现问题,所有请求都会降级处理。
- 而Hystrix同时会记录请求量,当一定时间内,失败的请求或者错误的请求的百分比达到阈值,会触发熔断,而断路器完全打开。
- 默认失败比例的阈值为50%,请求次数最少不低于20次(但是可根据实际场景修改为合适的数据)
- half open:
- 半开状态,open状态不会永久不变。此状态则表示Hystrix尝试恢复请求的正常访问,这时,会释放部分请求通过,而一旦确定这些请求都是健康的,正确的,则会关闭断路器,进入closed状态。
- 反之,则会继续保持打开,再次进入休眠计时。(休眠计时默认5s)
1.2 实际项目中演示片段
2. 案例演示
- 构建服务提供方模块。ex:cloud-provider-hystrix8001
- pom.xml文件中引入依赖
<dependencies>
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.usan.commons</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
- 编写配置文件application.yml
server:
port: 8001
spring:
application:
name: cloud-payment-service # 服务名称
eureka:
client:
register-with-eureka: true # 注册进Eureka服务中心
fetch-registry: true # 检索服务中心的其他服务
service-url: # 设置EurekaServer 交互的地址
# 使用了服务集群
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
- service层的方法设置服务熔断
@Service
public class PaymentService {
// 服务熔断
@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
@HystrixProperty(name="circuitBreaker.enabled",value = "true"), // 是否开启断路器
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "10"), // 请求次数
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "60"), // 失败率达到多少后跳闸
// 整体意思是:10秒内10次请求,有6次失败,就跳闸
})
public String paymentCircuitBreaker(Integer id){
// 模拟发生异常
if(id < 0){
throw new RuntimeException("******id,不能为负数……");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" +"调用成功,流水号:"+ serialNumber;
}
public String timeoutHandler(Integer id) {
return "id不能为负,请重试……";
}
}
- 编写controller
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
return paymentService.paymentCircuitBreaker(id);
}
}
- 编写启动类,并开启熔断(使用注解
@EnableCircuitBreaker
)
//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker // 开启服务熔断
@SpringCloudApplication // 组合注解 此注解包含了以上三个注解
public class HystrixPaymentApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentApplication.class, args);
}
}
- 启动服务并测试
- 多次测试
id<0
的请求。之后,再测试id>0的情况,发现还是调用异常的结果。只有过一段时间之后才会显示调用正常。这正好符合断路器的原理。
小结
- 服务熔断过程中,会发生服务降级。但,二者没有任何关系,类似于Java与JavaScript。
- 服务降级:当访问某个服务出现了异常之后,用户不需要无休止的等待,而是立马给用户返回一个备选方案(友好的提示)
- 服务熔断:存在一个保护恢复机制。一旦请求异常或错误且一定时间内达到错误请求设置的阈值后,断路器打开,熔断开启,阻止错误请求,但是这个时间是有时效的,失效后,会再次恢复链接。
- 使用yml的方式进行熔断的配置方式:
hystrix:
command:
default:
circuitBreaker:
enabled: true
requestVolumeThreshold: 10
sleepWindowInMilliseconds: 10000
errorThresholdPercentage: 60
- 用户在指定的时间范围(默认10s)之内的请求总数达到指定的数量之后,如果不健康的请求(超时、异常)占总请求数量的百分比(50%)达到了指定的阈值之后,就会触发熔断。
- 熔断机制的注解是:
@HystrixCommand