专栏首页爱编码SpringCloud之Hystrix

SpringCloud之Hystrix

简介

在分布式环境中,许多服务依赖关系中的一些必然会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止跨服务的级联故障并提供回退选项来实现这一点,所有这些选项都提高了系统的总体弹性。

目标

Hystrix的设计目的如下:

  • 为通过第三方客户端库访问的依赖项(通常通过网络)提供保护和控制延迟和故障。
  • 停止复杂分布式系统中的级联故障。
  • 故障快速恢复。
  • 在可能的情况下,后退并优雅地降级。
  • 启用近实时监视、警报和操作控制。

背景

为了解决什么问题?

复杂分布式体系结构中的应用程序有几十个依赖项,每个依赖项在某个时候都不可避免地会失败。如果主机应用程序没有从这些外部故障中隔离出来,那么它就有可能与这些外部故障一起宕机。

例如,对于一个依赖于30个服务的应用程序,其中每个服务都有99.99%的正常运行时间,您可以这样期望:

99.9930 = 99.7% uptime 0.3% of 1 billion requests = 3,000,000 failures 2+ hours downtime/month even if all dependencies have excellent uptime.

现实通常更糟。 即使当所有依赖项都运行良好时,即使0.01%的停机时间对几十个服务中的每个服务的总体影响也相当于一个月潜在的停机时间(如果您不为恢复而设计整个系统)。

如下面的图演变:

当一切正常时,请求流可以是这样的:

当许多后端系统之一成为潜在,它可以阻止整个用户请求:

对于高流量,一个后端依赖项成为潜在,可能会导致所有服务器上的所有资源在几秒钟内饱和。 应用程序中通过网络或客户机库到达可能导致网络请求的每个点都是潜在故障的来源。比故障更糟的是,这些应用程序还可能导致服务之间的延迟增加,从而备份队列、线程和其他系统资源,从而导致系统中出现更多级联故障。

工作原理

工作流程图:

工作流程图

1. 构造一个HystrixCommand或HystrixObservableCommand对象

第一步是构造一个HystrixCommand或HystrixObservableCommand对象来表示对依赖项的请求。将请求发出时需要的任何参数传递给构造函数。 如果期望依赖项返回单个响应,则构造一个HystrixCommand对象。例如:

HystrixCommand command = new HystrixCommand(arg1, arg2);

如果期望依赖项返回发出响应的可观察对象,则构造一个HystrixObservableCommand对象。例如:

HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);
2.执行命令

有四种方法可以执行命令,使用以下四种方法之一的Hystrix命令对象(前两种方法只适用于简单的HystrixCommand对象,不适用于HystrixObservableCommand):

  • `execute()` — blocks, then returns the single response received from the dependency (or throws an exception in case of an error)
  • `queue()` — returns a Future with which you can obtain the single response from the dependency
  • `observe()` — subscribes to the Observable that represents the response(s) from the dependency and returns an Observable that replicates that source Observable
  • `toObservable()` — returns an Observable that, when you subscribe to it, will execute the Hystrix command and emit its responses
3.是否缓存了响应

如果为该命令启用了请求缓存,并且在缓存中可用对请求的响应,则此缓存的响应将立即以可观察到的形式返回。

4. 电路打开了吗?

当您执行该命令时,Hystrix将与断路器一起检查电路是否打开。 如果电路打开(或“跳闸”),那么Hystrix将不执行命令,而是将流路由到(8)获取回退。 如果电路被关闭,则流继续到(5),检查是否有可用的容量来运行命令。

5.线程池/队列/信号量是否已满?

如果与该命令关联的线程池和队列(或信号量,如果不在线程中运行)已满,那么Hystrix将不执行该命令,而是立即将流路由到(8)获取回退。

6.HystrixObservableCommand.construct()或HystrixCommand.run ()

这里,Hystrix通过为此目的编写的方法调用对依赖项的请求,方法如下:

  • `HystrixCommand.run()` — returns a single response or throws an exception
  • `HystrixObservableCommand.construct()` — returns an Observable that emits the response(s) or sends an onError notification

如果run()或construct()方法超过了命令的超时值,线程将抛出一个TimeoutException(如果命令本身不在自己的线程中运行,则单独的计时器线程将抛出一个TimeoutException)。在这种情况下,Hystrix将响应路由到8。获取回退,如果最终返回值run()或construct()方法没有取消/中断,那么它将丢弃该方法。 请注意,没有办法强制潜在线程停止工作——Hystrix在JVM上能做的最好的事情就是抛出InterruptedException。如果由Hystrix包装的工作不尊重interruptedexception,那么Hystrix线程池中的线程将继续它的工作,尽管客户机已经收到了TimeoutException。这种行为可能会使Hystrix线程池饱和,尽管负载“正确释放”。大多数Java HTTP客户端库不解释interruptedexception。因此,请确保正确配置HTTP客户机上的连接和读/写超时。 如果该命令没有抛出任何异常并返回一个响应,那么Hystrix将在执行一些日志记录和度量报告之后返回此响应。在run()的情况下,Hystrix返回一个可观察的对象,该对象发出单个响应,然后发出一个onCompleted通知;在construct()的情况下,Hystrix返回由construct()返回的相同的可观察值。

7.计算电路健康

Hystrix向断路器报告成功、失败、拒绝和超时,断路器维护一组滚动计数器,用于计算统计数据。 它使用这些统计数据来确定电路应该在什么时候“跳闸”,在这一点上,它会短路任何后续的请求,直到恢复期结束,在此期间,它会在第一次检查某些健康检查之后再次关闭电路。

8.回退

Hystrix试图恢复你的回滚命令执行失败时:当一个异常的构造()或()运行(6),当命令电路短路,因为打开(4),当命令的线程池和队列或信号能力(5),或者当命令已超过其超时长度。 详情参考官网:https://github.com/Netflix/Hystrix/wiki/How-it-Works#8-get-the-fallback

9. 返回成功的响应

如果Hystrix命令成功,它将以可观察到的形式返回响应或响应给调用者。根据您如何调用上面步骤2中的命令,这个可观察对象可能在返回给您之前进行转换:

  • execute() — 以与.queue()相同的方式获取一个Future,然后在这个Future上调用get()来获取可观察对象发出的单个值.
  • queue() — 将可观察对象转换为BlockingObservable,以便将其转换为未来,然后返回此未来
  • observe() — 立即订阅可观察对象,并开始执行命令的流;返回一个可观察对象,当您订阅该对象时,将重播排放和通知
  • toObservable() — 返回可观察值不变;您必须订阅它,才能真正开始执行命令的流程

更多原理可以移步官网 https://github.com/Netflix/Hystrix/wiki/How-it-Works

使用

加入依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  </dependency>
在ribbon中使用

使用@EnableHystrix开启

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
public class CloudServiceRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudServiceRibbonApplication.class, args);
    }


    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

该注解对该方法创建了熔断器的功能,并指定了fallbackMethod熔断方法,熔断方法直接返回了一个字符串,字符串为"hi,"+name+",sorry,error!"

@Service
public class TestService {


    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError")
    public String hiService(String name) {
        return restTemplate.getForObject("http://CLOUD-EUREKA-CLIENT/hi?name="+name,String.class);
    }

    public String hiError(String name) {
        return "hi,"+name+",sorry,error!";
    }

}
在Feign中使用

feign.hystrix.enabled: true 开启hystrix

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8765
spring:
  application:
    name: cloud-service-feign

feign.hystrix.enabled: true

@EnableFeignClients启动

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
public class CloudServiceFeginApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudServiceFeginApplication.class, args);
    }

}

fallback:配置连接失败等错误的返回类

@FeignClient(value = "cloud-eureka-client",fallback = TestServiceHystric.class)
public interface TestService {

    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    String sayHiFromClientOne(@RequestParam(value = "name") String name);

}

当访问接口有问题时,直接调用此接口返回。

@Component
public class TestServiceHystric implements  TestService{
    @Override
    public String sayHiFromClientOne(String name) {
        return "sorry "+name;
    }
}

更多使用技巧可参考官网: https://github.com/Netflix/Hystrix/wiki/How-To-Use

总结

在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。

熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。

更多优质文章:

  1. https://dwz.cn/nehIuSjZ
  2. http://blog.didispace.com/tags/Hystrix/

本文分享自微信公众号 - 爱编码(ilovecode),作者:明大侦探

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java的CopyOnWriteArrayList

    ArrayList并不是线程安全的,在读线程在读取ArrayList的时候如果有写线程在写数据的时候,基于fast-fail机制,会抛出ConcurrentMo...

    用户3467126
  • Java 浅拷贝和深拷贝

    Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。

    用户3467126
  • Elasticsearch的CRUD

    本文使用的Elasticsearch版本为6.5.4,上文主要介绍了它的Index(数据库)和Mapping(表结构),那么本文主要记录一下关于Elastics...

    用户3467126
  • unity htc vive使用

    本文介绍如何在Unity中使用HTC vive设备,当前VR作为市场比较火热的热点,HTC VIVE设备作为三大供应商之一,许多人购买了该设备,却不知道如何使用...

    庞小明
  • 错误 RC1015: 无法打开包含文件 'XTToolkitPro.rc'

    XtremeToolkitPro作为VC++/MFC平台下目前最流行的GUI界面库之一,安装和使用都很方便。不过,在实际使用中...

    步行者08
  • Spring Cloud 入门教程5、服务容错监控:Hystrix Dashboard

    上一篇我们介绍了Hystrix的基础使用,我们可以通过Hystrix做到依赖隔离和熔断等操作。但是只有工具的使用而没有监控,我们就无法在第一时间发现出现问题的依...

    KenTalk
  • 中国首批新能源车主陷入困境:修不了,也修不起!

    在现在这个社会,小汽车已经成为了我们说过很多次的话题了,现在人们购买汽车已经越来越注重汽车的环保性,现在很多的汽车厂商都注重研发环保汽车,现在绝大多数的公交车使...

    钱塘数据
  • Gmail查找存档的邮件

    邮件归档后将从您的收件箱中删除,但是仍保留在您的账户中,便于之后查找。归档操作就像将邮件放入档案柜中妥善保管一样,而不是将其丢入垃圾箱。

    技术小黑屋
  • 斯坦福大学开源能跑能跳的四足机器人Doggo,DIY一台只需3000美元

    更重要的是,设计是完全开源的,开源计划意味着任何人都可以下载并构建DOGGO,成本大约3000美元。

    AiTechYun
  • 零基础使用Django2.0.1打造在线教育网站(二十四):全局页面配置

    努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

    编程思录

扫码关注云+社区

领取腾讯云代金券