Hystrix 服务熔断
- 容错机制:微服务和分布式里面,容错是必须要考虑的!通常的做法有两种
- 一种是重试机制,对于预期的短暂故障问题,可以重试解决;
- 二是使用断路器模式,即将受保护的服务封装到一个可以监控故障的断路器里面,当故障达到一定的值,断路器将会跳闸,断路器对象返回错误!
断路器状态机: 1.closed,熔断器关闭状态,调用失败次数累计到一定阈值/比例,启动熔断机制,进入打开状态 2.open,熔断器打开状态,对服务直接返回错误,直接服务降级 3.half open,熔断器打开状态达到了一定的时间,会进入半熔断状态,允许定量的服务请求主逻辑。如果都调用成功,或者一定比例成功,则认为恢复,关闭熔断器;否则,熔断器回到打开状态
断路器模式设计状态机(三种状态)
- Closed(熔断器的关闭状态):熔断器关闭状态,调用失败次数累计到一定阈值/比例,启动熔断机制,进入打开状态
- Open(熔断器打开状态):熔断器打开状态,对服务直接返回错误,直接服务降级
- Half Open(熔断器半熔断状态):熔断器打开状态达到了一定的时间,会进入半熔断状态,允许定量的服务请求主逻辑。如果都调用成功,或者一定比例成功,则认为恢复,关闭熔断器;否则,熔断器回到打开状态
- sleepWindowInMilliseconds:休眠时间窗口
- requestVolumeThreshold:最小的请求数
- errorThresholdPercentage:服务错误百分比(比如百分之70,就是10个请求,有7个错误)
Product 微服务项目
@PostMapping("/listForOrder")
public List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return productService.findList(productIdList);
}
Order 微服务项目
package com.imooc.order.controller;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {
@HystrixCommand(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"), // 错误率
})
@GetMapping("/getProductInfoList")
public String getProductInfoList(@RequestParam("number") Integer number) {
if (number % 2 == 0) {
return "success";
}
RestTemplate restTemplate = new RestTemplate();
return restTemplate.postForObject("http://127.0.0.1:8005/product/listForOrder",
Arrays.asList("157875196366160022"),
String.class);
}
private String defaultFallback() {
return "默认提示:太拥挤了, 请稍后再试~~";
}
}
- 此时默认 1s(为了达到降级效果),这里模拟了一个奇数偶数判断是为了模拟熔断的场景。