系统出现了服务雪崩(当微服务调用时,当链路的某个出现了异常,对该微服务的调用耗费会占用较大的系统资源,从而引起系统崩溃),Hystrix就出现了。
它主要就是当某个服务发生故障的时候,给你返回个备选响应,不让你长期没必要的占用以及等待。
链接:Hystrix官网
一、基本概念
1.1 服务降级
- 服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,直接返回一个提前准备好的fallback(退路)错误处理信息。
1.2 服务熔断
- 服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用,以服务降级的方式进行处理。
熔断VS降级
* 目标一致:都是从可用性和可靠性出发,为了防止系统崩溃;
* 用户体验类似:最终都让用户体验到的是某些功能暂时不可用;
* 触发原因不同:服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
1.3 服务限流
- 高并发的情况下,限制调用数量
二、处理
1.1 服务降级
服务降级可以从两方面着手:客户端、服务端
1. 服务端
从服务端进行限制,规定几秒钟是成功,否则就返回延时的处理方法,作为服务降级的fallback。
启动类上开启注解
@EnableCircuitBreaker
或@EnableHystrix
@EnableHystrix的源码可以发现,它继承了@EnableCircuitBreaker,并对它进行了在封装。
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80 {
public static void main(String[] args){
SpringApplication.run(OrderHystrixMain80.class, args);
}
}
在业务层去处理超时响应的结果
这里的业务处理,演示超时响应的情况。
// 目标方法和回退方法参数和返回类型要一致,否则就会报错 Hystrix fallback method wasn‘t found
@HystrixCommand(fallbackMethod = "testTimeoutHandler"
// 表示当testTimeout方法响应的时间超过3s就会跳转到testTimeoutHandler这个方法
,commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")}
)
public String testTimeout(Integer id) {
// 暂停几秒钟线程
try{
TimeUnit.SECONDS.sleep(5);
}catch (InterruptedException e){
e.printStackTrace();
}
return "Timeout :" + id + "线程池:" + Thread.currentThread().getName();
}
public String testTimeoutHandler(Integer id) {
return "(╯‵□′)╯︵┻━┻ 服务端 (╯‵□′)╯︵┻━┻ " + id;
}
服务端测试
2. 客户端
yaml文件
# 开启客户端Hystrix的熔断 ,默认的超时时间为1s
feign:
hystrix:
enabled: true
# Hystrix的单独配置,即修改默认超时时间为2s.客户端如果2s没得到响应,会调用处理方法
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000
启动类添加
@EnableHystrix
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80 {
public static void main(String[] args){
SpringApplication.run(OrderHystrixMain80.class, args);
}
}
控制层
@RestController
public class PaymentController {
@Resource
private PaymentFeign paymentFeign;
@GetMapping(value = "/payment/hystrix/timeout/{id}")
public Result<String> testTimeout(@PathVariable("id") Integer id) {
return paymentFeign.testTimeout(id);
}
}
Feign接口
// fallback : 指定超时的处理方法为 PaymentHystrix
@FeignClient(value = "cloud-provider-hystrix-payment",fallback = PaymentHystrix.class)
public interface PaymentFeign {
@GetMapping(value = "/payment/hystrix/timeout/{id}")
Result<String> testTimeout(@PathVariable("id") Integer id) ;
}
新建超时处理方法PaymentHystrix ,实现Feign接口
@Component
public class PaymentHystrix implements PaymentFeign {
@Override
public Result<String> testOK(Integer id) {
return new Result<String>(200,"success","----------------testOK");
}
@Override
public Result<String> testTimeout(Integer id) {
return new Result<String>(200,"success","----------------testTimeout");
}
}
测试
-------------------分割线
还有一种就是在控制层进行处理,仅作为学习扩展。
控制层
采用1v1指定的方式进行处理
@RestController
@DefaultProperties(defaultFallback = "paymentGlobalFallBack")
public class PaymentController {
@Resource
private PaymentFeign paymentFeign;
@GetMapping(value = "/payment/hystrix/timeout/{id}")
// @HystrixCommand : 实现控制层的超时控制
// fallbackMethod : 目标方法和回退方法参数和返回类型要一致 value指定为2s
@HystrixCommand(fallbackMethod = "testTimeoutFallback"
,commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "2000")}
)
}
public Result<String> testTimeout(@PathVariable("id") Integer id) {
return paymentFeign.testTimeout(id);
}
public Result<String> testTimeoutFallback(@PathVariable("id") Integer id){
return new Result<String>(200,"success","客户端:(╯‵□′)╯︵┻━┻ " + id);
}
测试
全局配置
控制层
@RestController
@DefaultProperties(defaultFallback = "paymentGlobalFallBack")
public class PaymentController {
@Resource
private PaymentFeign paymentFeign;
@GetMapping(value = "/payment/hystrix/timeout/{id}")
@HystrixCommand
public Result<String> testTimeout(@PathVariable("id") Integer id) {
return paymentFeign.testTimeout(id);
}
/**
* 配置全局兜底方案不能有形参
*/
public Result<String> paymentGlobalFallBack(){
return new Result<String>(200,"success","GLOBAL");
}
}
测试
1.2 服务熔断
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。当检测到该节点微服务响应正常后恢复调用链路。熔断机制的注解是@HystrixCommand。
在一定时间内出错达到一定的阈值5秒内20次调用失败,熔断器打开,进行服务降级。在休眠窗口到期后,熔断器尝试半开,发送服务,熔断器关闭:如果成功,恢复访问;否则休眠窗口重新计时,继续服务降级。
业务处理类 service层
@Override
@HystrixCommand(fallbackMethod = "testCircuitBreakerFallBack",commandProperties = {
// 在进入熔断开启状态一段时间之后(Hystrix默认是5秒),熔断器会进入半熔断状态。
// 是否开启断路器
@HystrixProperty(name= "circuitBreaker.enabled",value = "true"),
// 设置在一个滚动窗口中,打开断路器的最少请求数。默认为20。换句话说,假如某个窗口期内的请求总数都不到该配置值,那么断路器连发生的资格都没有。断路器在该窗口期内将不会被打开。
@HystrixProperty(name= "circuitBreaker.requestVolumeThreshold",value = "10"),
// 休眠时间窗口期 10s
@HystrixProperty(name= "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),
// 失败率到达多少后跳闸
@HystrixProperty(name= "circuitBreaker.errorThresholdPercentage",value = "60"),
})
public String testCircuitBreaker(Integer id) {
if (id < 0){
throw new RuntimeException("-------------------------id不能为负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + ",调用成功,流水号:" + serialNumber;
}
public String testCircuitBreakerFallBack(Integer id){
return "id不能为负数," + id;
}