微服务断路器Istio与Hystrix比较

栏目: 后端 · 发布时间: 7年前

内容简介:无可否认,在过去几年中,像Docker和Kubernetes这样的技术,彻底改变了我们对软件开发和部署方式。断路器模式是在微服务架构中广泛采用的那些模式之一。我们将比较实现它的两种不同方法的优缺点:Hystrix和Istio。想象一个非常简单的微服务架构,包括:

无可否认,在过去几年中,像 Docker 和Kubernetes这样的技术,彻底改变了我们对软件开发和部署方式。断路器模式是在微服务架构中广泛采用的那些模式之一。我们将比较实现它的两种不同方法的优缺点:Hystrix和Istio。

微服务同步通信的核心问题

想象一个非常简单的微服务架构,包括:

  1. 后端服务
  2. 前端服务

让我们假设后端和前端通过同步HTTP调用进行通信。

客户端C1并C2调用前端来检索一些信息。由于前端没有所有必需的数据,因此它会调用后端来获取缺失的部分。

但由于网络通信,可能会发生很多事情:

  • 前端和后端之间出现网络故障
  • 后端可能是因为一个错误的宕机
  • 后端服务依赖的数据库宕机

而按照墨菲定律(“凡是可能出错就会出错”),前端和后端之间的通信失败是迟早的事。

在这种情况下唯一合理的解决方案是快速失败: 应该让前端知道后端出现问题,并立即将故障返回给自己的客户端。

断路器模式

在电路领域中,断路器是设计用于保护电路的自动操作的电气开关。其基本功能是在检测到故障后中断电流。然后可以在故障解决后重置(手动或自动)以恢复正常操作。

应用于上述超时问题的设计模式。它背后的流程非常简单:

  • 如果呼叫失败,请将失败呼叫的数量增加1
  • 如果失败的呼叫数超过某个阈值,请打开电路
  • 如果电路处于打开状态,则立即返回错误或默认响应
  • 如果电路开路且经过一段时间,则半开电路
  • 如果电路半开,下一次呼叫失败,请再次打开
  • 如果电路半开,下一次通话成功,请将其关闭

微服务断路器Istio与Hystrix比较

Istio断路器

Istio 是服务网格,是微服务应用程序的可配置基础设施层。它使服务实例之间的通信变得灵活,可靠和快速,并提供服务发现,负载平衡,加密,身份验证和授权,对断路器模式的支持以及其他功能。

Istio的控制平面在底层集群管理平台上提供了一个抽象层,例如Kubernetes,Mesos等,并且需要以这种方式管理您的应用程序。

作为其核心,Istio使用 边车容器模式 :这是一个位于应用程序实例前面的Envoy代理实例,以及管理它们的工具Pilot。这种代理策略有许多优点:

  • HTTP,gRPC,WebSocket和TCP流量的自动负载平衡。
  • 通过丰富的路由规则,重试,故障转移和故障注入,对流量行为进行细粒度控制。
  • 可插入的策略层和配置API,支持访问控制,速率限制和配额。
  • 群集中所有流量的自动度量标准,日志和跟踪,包括群集入口和出口。
  • 通过强大的基于身份的身份验证和授权,在群集中实现安全的服务到服务通信。

由于对后端的出口调用通过Envoy代理,因此很容易检测到它们何时超时。然后代理可以拦截进一步的调用并立即返回,有效地快速失败。特别是,这使得断路器图案能够以黑盒方式操作。

配置Istio断路器

正如我们所说,Istio在您选择的集群管理平台上构建,并且需要通过它来部署您的应用程序。根据以下模型,Kubernetes 实现断路器模式:通过一个 DestinationRule或更具体的路径策略TrafficPolicy调用 - >OutlierDetection:

微服务断路器Istio与Hystrix比较

参数如下:

consecutiveErrors: 在断路器打开前的返回5xx的数量。

interval:断路器检查分析之间的时间间隔。

baseEjectionTime:最短打开时间。电路将保持等于最小喷射持续时间和断路打开次数的乘积。

maxEjectionPercent:负载平衡池中可以弹出的上游服务的最大主机百分比。

与前面标准的断路器相比,有两个主要偏差:

  • 没有半开状态这样的事情。但是,断路器保持打开的持续时间取决于被叫服务之前失败的次数。不断失效的服务将导致断路器的打开持续时间越来越长。
  • 在基本模式中,有一个叫做应用程序(后端)。在更现实的生产设置中,可能会在负载均衡器后面部署同一应用程序的多个实例。有些实例可能会失败,有些可能会失效,而且由于Istio也扮演负载均衡器的角色,它能够跟踪失败的实例并将它们从负载平衡池中弹出删除,直到某一点:maxEjectionPercent的角色属性将保留实例池中的一小部分。

断路器Istio接近是黑盒子。它需要一个高视点支架,并且只能在出现问题时打开断路。另一方面,它设置起来非常简单,并且不需要任何底层代码知识,并且可以将其配置为事后想法。

Hystrix断路器

Hystrix 是一个最初由Netflix提供的开源 Java 库。它是一个延迟和容错库,旨在隔离对远程系统,服务和第三方库的访问点,停止级联故障,并在复杂的分布式系统中实现弹性,在这些系统中,故障是不可避免的。

Hystrix有许多功能,包括:

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

当然,断路器模式在这些功能中占有一席之地。因为Hystrix是一个库,它以白盒方式实现它。

Resilience4J

Netflix最近宣布已停止开发Hystrix库,转而采用不太知名的 Resilience4J 项目。

即使客户端代码可能有点不同,Hystrix和Resilience4J之间的方法也是类似的。

Hystrix断路器示例

考虑电子商务Web应用程序的情况。该应用程序的体系结构由不同的微服务构成,每个服务都基于业务功能:

  • 认证
  • 目录浏览
  • 购物车管理
  • 定价和报价
  • 等等。

显示目录项时,将查询定价/报价微服务的价格。如果中间通信断开,将不会发回任何价格,也无法订购任何东西。

从商业角度来看,任何停机时间不仅会对品牌的感知产生影响,还会降低销售额。尽管价格并不完全正确,但大多数销售策略仍倾向于出售。实现此销售策略的解决方案可以是在可用时缓存定价/报价服务返回的价格,并在服务停止时返回缓存价格。

Hystrix通过提供断路器实现允许该方法,该电路断路器实现允许在电路断开时进行回退。

这是Hystrix模型的简化类图:

微服务断路器Istio与Hystrix比较

魔术发生在HystrixCommand方法run()和getFallback():

  • run()是实际代码,例如从报价服务中获取价格
  • getFallabck()当断路器打开时获得后备结果,例如返回缓存价格

这可以转换为以下代码,使用Spring RestTemplate:

<b>public</b> <b>class</b> FetchQuoteCommand <b>extends</b> HystrixCommand<Double> {

    <b>private</b> <b>final</b> UUID productId;                                               <font><i>// 1</i></font><font>
    <b>private</b> <b>final</b> RestTemplate template;                                        </font><font><i>// 2</i></font><font>
    <b>private</b> <b>final</b> Cache<UUID, Double> cache;                                    </font><font><i>// 3</i></font><font>

    <b>public</b> FetchQuoteCommand(UUID productId,
                             RestTemplate template,
                             Cache<UUID, Double> cache) {
        <b>super</b>(HystrixCommandGroupKey.Factory.asKey(</font><font>"GetQuote"</font><font>));        </font><font><i>// 4</i></font><font>
        <b>this</b>.template = template;
        <b>this</b>.cache = cache;
        <b>this</b>.productId = productId;
    }

    @Override
    <b>protected</b> Double run() {
        Double quote = template.getForObject(</font><font>"https://acme.com/api/quote/{id}"</font><font>, // 5
                                             Double.<b>class</b>,
                                             productId);
        cache.put(productId, quote);                                            </font><font><i>// 6</i></font><font>
        <b>return</b> quote;
    }

    @Override
    <b>protected</b> Double getFallback() {
        <b>return</b> cache.get(productId);                            </font><font><i>// 7</i></font><font>
    }
}
</font>

这需要一些解释:

  1. 该命令包装了产品的id,模仿为a UUID。
  2. Spring RestTemplate用于进行REST调用。任何其他选择都可以。
  3. 共享JCache实例,用于在服务可用时存储引号。
  4. Hystrix命令需要组密钥,以便在需要时将它们组合在一起。这是Hystrix的另一个特性,超出了本文的范围。有兴趣的读者可以阅读 Hystrix wiki 中的命令组。
  5. 执行对引用服务的调用。如果失败,则启动Hystrix断路器流量。
  6. 如果调用成功,则将返回的引用缓存在JCache共享实例中。
  7. 在getFallback()当断路器打开时调用。在这种情况下,从缓存中获取引用。

Hystrix wiki具有 更高级的示例, 例如 后备本身就是一个需要执行的命令。

(banq注:更简单Springcloud应用:)

@HystrixCommand(fallbackMethod = <font>"createProduct"</font><font>)
 <b>public</b> Product getProduct(@RequestParam String productId) {
      ...
    }

<b>private</b> Product createProduct(String productId) {
        Product product = <b>new</b> Product();
        product.setId(</font><font>"999999"</font><font>);
        product.setName(</font><font>"网络问题"</font><font>);
        <b>return</b> product;

    }
</font>

将Hystrix与Spring Cloud集成

虽然上面的代码有效,但每次引用时都需要创建一个Hystrix命令对象。

Spring Cloud 是一个构建在Spring Boot之上的库(它本身构建在Spring框架之上),它提供了与Spring的完美集成。它允许在处理Hystrix命令对象的实例化时,只注释所需的回退方法:

<b>public</b> <b>class</b> FetchQuoteService {

    <b>private</b> <b>final</b> RestTemplate template;
    <b>private</b> <b>final</b> Cache<UUID, Double> cache;

    <b>public</b> SpringCloudFetchQuoteCommand(RestTemplate template,
                                        Cache<UUID, Double> cache) {
        <b>this</b>.template = template;
        <b>this</b>.cache = cache;
    }

    @HystrixCommand(fallbackMethod = <font>"getQuoteFromCache"</font><font>)                       </font><font><i>// 1</i></font><font>
    <b>public</b> Double getQuoteFor(UUID productId) {                                 </font><font><i>// 2</i></font><font>
        Double quote = template.getForObject(</font><font>"https://acme.com/api/quote/{id}"</font><font>, // 3
                                             Double.<b>class</b>,
                                             productId);
        cache.put(productId, quote);                                            </font><font><i>// 4</i></font><font>
        <b>return</b> quote;
    }

    <b>public</b> Double getQuoteFromCache(UUID productId) {                           </font><font><i>// 5</i></font><font>
        <b>return</b> cache.get(productId);
    }
}
</font>
  1. 该方法应注明@HystrixCommand。该fallbackMethod元素引用了回退方法。显然,这将通过反射来处理,并且不是类型安全的 - 毕竟这是一个字符串。
  2. Spring Cloud Hystrix允许在方法调用时传递产品的id参数。与上面的简单Hystrix命令相比,这允许具有通用服务对象。Hystrix命令的创建由Spring Cloud在运行时处理。
  3. 核心逻辑不会改变。
  4. 同样,缓存过程保持不变。
  5. 后备方法是常规方法。 它将使用与main方法完全相同的参数值进行调用,因此它必须具有相同的参数类型(以相同的顺序)。因为该getQuoteFor()方法接受UUID,所以此方法也是如此。

Hystrix,无论是独立的还是由Spring Boot Cloud包装,都需要在代码级别处理断路器。因此,它需要提前计划,并且更改需要部署更新的二进制文件。但是,当出现问题时,可以实现非常精细的定制行为。

Istio vs Hystrix:断路器之战

断路器模式是处理服务可用性不足的方法之一:它不是排队请求和阻塞调用者,而是快速失败并立即返回。

有两种方法可以实现断路器,黑盒方式和白盒方式。Istio作为代理管理工具,采用黑盒方式。它实现起来很简单,它不依赖于底层技术堆栈,它可以被配置为事后的想法。

另一方面,Hystrix库使用白盒方式。它允许拥有所有不同类型的后备:

  • 单个默认值
  • 缓存
  • 呼叫其他服务。

它还提供级联回退。这些附加功能需要付出代价:它需要在仍处于开发阶段时做出后退决策。

两种方法之间的最佳匹配可能取决于一个人自己的背景:在某些情况下,例如引用服务,带有后备的白盒策略可能更适合,而对于其他情况,快速失败可能完全可以接受,例如集中式远程日志服务。


以上所述就是小编给大家介绍的《微服务断路器Istio与Hystrix比较》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Data-intensive Text Processing With Mapreduce

Data-intensive Text Processing With Mapreduce

Jimmy Lin、Chris Dyer / Morgan and Claypool Publishers / 2010-4-30 / USD 40.00

Our world is being revolutionized by data-driven methods: access to large amounts of data has generated new insights and opened exciting new opportunities in commerce, science, and computing applicati......一起来看看 《Data-intensive Text Processing With Mapreduce》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具