SpringCloud浅尝(八)——Hystrix

Hystrix 具备服务降级、服务容错、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能。
多层服务调用中,较低级别的服务中的服务故障可能导致用户级联故障。当对特定服务的呼叫达到一定阈值时(Hystrix中的默认值为5秒内的20次故障),电路打开,不进行通话。在错误和开路的情况下,开发人员可以提供后备。
下图来自官方网站
SpringCloud浅尝(八)——Hystrix
文章图片


Hystrix特性
1.请求熔断: 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN).这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN).
2.服务降级:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。
3.依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用两外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放。后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在哪里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用。
4.请求缓存:比如一个请求过来请求用户的数据,你后面的请求也过来请求同一个用户的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。
5.请求合并:我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。

我们前面EurekaDiscovery2实例中,使用了Feign来调用EurekaDiscovery中的接口,Feign内部已包含了hystrix。下面我们先使用Feign来实现降级融断。
在EurekaDiscovery2配置中添加

feign: hystrix: enabled: true# 开启hystrix

我们添加一个Fallback类并实现HelloRemote接口
@Component public class HelloFallback implements HelloRemote { @Override public String home(@RequestParam("name") String name) { return name+"现在太拥挤了, 请稍后重试~-Feign"; } }

我们指定fallback类为HelloFallback
@FeignClient(name= "eurekadiscovery", fallback = HelloFallback.class) public interface HelloRemote { @GetMapping("/hi") public String home(@RequestParam("name") String name); }

下面我们启动实例来验证一下
正常调用:
SpringCloud浅尝(八)——Hystrix
文章图片

我们模拟EurekaDiscovery挂掉(关闭),触发了服务降级
SpringCloud浅尝(八)——Hystrix
文章图片

超时导致服务降级,默认feign调用超时是1000毫秒,我们EurekaDiscovery中将线程sleep1000豪秒,同样出现了上面一样的服务降级。
我们可以通下面的配置来设置超时时间
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 3000

通过调整hystrix的超时时间,服务能正常调用
SpringCloud浅尝(八)——Hystrix
文章图片


当我们没有使用Feign时也可直接引用Hystrix组件来实现在,我们在项目中引入spring-cloud-starter-netflix-hystrix
启动类中我们添加注解@EnableCircuitBreaker 允许断路器
@SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class EurekaDiscovery2Application { @Bean @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(EurekaDiscovery2Application.class, args); }}


我们通过@HystrixCommand
@HystrixCommand(fallbackMethod = "fallback") public String home(@RequestParam("name") String name) { return restTemplate.getForEntity("http://EUREKADISCOVERY/hi?name="+name,String.class).getBody(); }public String fallback(String name) { return name+",现在太拥挤了, 请稍后重试~"; }

我们启动实例,能正常调用
SpringCloud浅尝(八)——Hystrix
文章图片

我们模拟EurekaDiscovery挂掉(关闭),触发了服务降级
【SpringCloud浅尝(八)——Hystrix】SpringCloud浅尝(八)——Hystrix
文章图片


我们还可以通过@DefaultProperties(defaultFallback = "defaultFallback"),来指定默认的FallBack函数,这样就不需要每个 @HystrixCommand 注解都指定一个FallBack函数了
@RestController @DefaultProperties(defaultFallback = "defaultFallback") public class HelloController { @Autowired privateRestTemplate restTemplate; @GetMapping("/hi") @HystrixCommand // @HystrixCommand(fallbackMethod = "fallback") public String home(@RequestParam("name") String name) { return restTemplate.getForEntity("http://EUREKADISCOVERY/hi?name="+name,String.class).getBody(); }public String fallback(String name) { return name+",现在太拥挤了, 请稍后重试~"; }public String defaultFallback() { return "现在太拥挤了, 请稍后重试~"; }

这样我们降级后就会调用默认的FallBack函数
SpringCloud浅尝(八)——Hystrix
文章图片

我们还可以通过@HystrixCommand来设定超时时间,我们一般都是采用在配置文件中设置超时间时间。
@HystrixCommand(commandProperties = { // 设置超时时间为3秒 @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "https://www.it610.com/article/3000") })

hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 3000 home: execution: isolation: thread: timeoutInMilliseconds: 1000




    推荐阅读