1 场景导入
在微服务架构中,我们会根据业务拆分为一个个服务,服务之间可以互相调用。但是,如果某些服务不可用了,可能会影响调用它的服务,以至于影响整个业务。我们这里举个例子,假设有A,B,C三个服务,并存在A调用B,B调用C的关系,当C的处理能力降低时,B发送请求给C却得不到返回,挂起的远程调用增加,使B的资源被消耗从而处理能力降低,从而影响到A,使其因为资源的消耗而变得不可用,最终,整个系统雪崩。
我们可以发现,性能较差的远程服务容易引起连锁反应,在整个应用程序生态系统中,如果没有保障措施,一个性能较差的服务可能会影响到整个系统。为解决这个问题,我们需要断路器。
2 什么是 Hystrix?
Hystrix 就是一个断路器,即容错管理工具,可以通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
好的,我们已经知道 Hystrix 的具体作用了。那么,什么是断路器呢?在微服务中,一个请求可能需要调用多个服务,如果一个服务出现故障,可能会发生连锁反应。当特定的服务的调用不可用到达阀值时,断路器会被打开,在断路器打开后,fallback 方法可以直接返回一个固定值,从而避免连锁故障。(Hystrix 的阀值是5秒20次)
断路器可以快速失败。若在一段时间内发现许多类似的错误,会令之后的多个调用快速失败,不再访问远程服务器,防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。
断路器记录最近调用发生错误的次数,然后决定允许操作继续,或者立即返回错误,它是保护服务高可用的最后一道防线。
3 断路器机制
当请求后端服务失败数量超过一定比例之后,所有请求会直接失败而不会发送到后端服务,在一段时间后,断路器会判断下一次请求的返回情况,若请求成功则恢复正常,否则所有请求继续直接失败。断路器具有自我检测并恢复的能力,可以避免发送大量无效请求影响系统吞吐量。
4 实战
Feign 中已经默认集成了 Hystrix,但它没有默认打开。想要使用断路器,需要在配置文件配置打开它,需要添加以下代码:
feign.hystrix.enabled=true
然后我们修改之前的 EurekaConsumer 项目下的 HelloWorldService 接口,在 @FeignClient 注解加入 fallbackFactory 的指定类:
package com.example.EurekaConsumer.Service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.example.EurekaConsumer.FallbackFactory.HelloWorldFallbackFactory;
//name为远程服务名,即远程服务spring.application.name设置的名字
@Component
@FeignClient(name= "producer",fallbackFactory = HelloWorldFallbackFactory.class)
public interface HelloWorldService {
//调用方法需要与远程服务中的方法名和参数一致
@RequestMapping("/helloWorld")
public String helloWorld(@RequestParam(value = "id")int id,@RequestParam(value = "saying")String saying);
}
fallbackFactory 指定类为 HelloWorldFallbackFactory ,然后我们需要实现这个类,其中这个类需要实现 FallbackFactory<HelloWorldService> 接口
package com.example.EurekaConsumer.FallbackFactory;
import org.springframework.stereotype.Component;
import com.example.EurekaConsumer.Service.HelloWorldService;
import feign.hystrix.FallbackFactory;
@Component
public class HelloWorldFallbackFactory implements FallbackFactory<HelloWorldService>{
@Override
public HelloWorldService create(Throwable cause) {
return new HelloWorldService() {
@Override
public String helloWorld(int id, String saying) {
return "出现了故障:" + cause + " id=" + id + "&saying" + saying;
}
};
}
}
我们先打开 Eureka,EurekaProducer,EurekaConsumer 三个项目,在浏览器输入 http://localhost:8082/helloWorld?id=4&saying=%E7%89%9B%E9%80%BC,其输出如下:
来自8080端口:序号为4的用户发布了一条新消息:牛逼
然后我们故意制造点故障,把 EurekaProducer 项目关闭,然后浏览器显示如下:
出现了故障:com.netflix.hystrix.exception.HystrixTimeoutException id=4&saying牛逼
证明我们的断路器使用成功。
参考:Feign方式使用Hystrix,通过FallbackFactory检查回退原因
史上最简单的SpringCloud教程 | 第四篇:断路器(Hystrix)(Finchley版本)
springcloud(四):熔断器Hystrix