Hystrix使⽤⼿册官⽅⽂档翻译
由于时间关系可能还没有翻译全,但重要部分已基本包含
本⼈⽔平有限,如有翻译不当,请多多批评指出,我⼀定会修正,谢谢⼤家。有关 ObrvableHystrixCommand 我有的部分选择性忽略了,因为常⽤的是 HystrixCommand,但每⼀个例⼦都有这两种 command 的解释
最好的学习⽅式其实还是看官⽅原⽂,下⾯附上链接
官⽅⽂档地址:
简述
什么是 Hystrix?
在分布式环境中,不可避免地会遇到所依赖的服务挂掉的情况,Hystrix 可以通过增加延迟容忍度与错误容忍度,来控制这些分布式系统的交互。Hystrix 在服务与服务之间建⽴了⼀个中间层,防⽌服务之间出现故障,并提供了失败时的 fallback 策略,来增加你系统的整体可靠性和弹性。
Hystrix 做了那些事情?
Hystrix 提供了以下服务
引⼊第三⽅的 client 类库,通过延迟与失败的检测,来保护服务与服务之间的调⽤(⽹络间调⽤最为典型)
阻⽌复杂的分布式系统中出现级联故障
快速失败与快速恢复机制
提供兜底⽅案(fallback)并在适当的时机优雅降级
提供实时监控、报警与操作控制
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.
实际情况往往更糟糕
完好情况下,请求流如下:
当⼀个依赖的节点坏掉时,将阻塞整个的⽤户请求:
流量⾼峰时,⼀个单节点的宕机或延迟,会迅速导致所有服务负载达到饱和。应⽤中任何⼀个可能通过⽹络访问其他服务的节点,都有可能成为造成潜在故障的来源。更严重的是,还可能导致服务之间的延迟增加,占⽤队列、线程等系统资源,从⽽导致多系统之间的级联故障。
更严重的是,当⽹络请求是通过第三⽅的⼀个⿊盒客户端来发起时,实现细节都被隐藏起来了,⽽且还可能频繁变动,这样发⽣问题时就很难监控和改动。如果这个第三⽅还是通过传递依赖的,主应⽤程序中根本没有显⽰地写出调⽤的代码,那就更难了。
⽹络连接失败或者有延迟,服务将会产⽣故障或者响应变慢,最终反应成为⼀个 bug。
所有上述表现出来的故障或延迟,都需要⼀套管理机制,将节点变得相对独⽴,这样任何⼀个单节点故障,都⾄少不会拖垮整个系统的可⽤性。
Hystrix 的设计原则是什么?
date是什么意思翻译
Hystrix 通过以下设计原则来运作:
防⽌任何⼀个单节点将容器中的所有线程都占满
通过快速失败,取代放在队列中等待
提供在故障时的应急⽅法(fallback)
使⽤隔离技术 (如 bulkhead, swimlane, 和 circuit breaker patterns) 来限制任何⼀个依赖项的影响⾯
提供实时监控、报警等⼿段
提供低延迟的配置变更
防⽌客户端执⾏失败,不仅仅是执⾏⽹络请求的客户端
Hystrix 如何时间它的⽬标?
如下:
将远程请求或简单的⽅法调⽤包装成HystrixCommand或者HystrixObrvableCommand对象,启动⼀个单独的线程来运⾏。
你可以为服务调⽤定义⼀个超时时间,可以为默认值,或者你⾃定义设置该属性,使得99.5%的请求时间都在该时间以下。
为每⼀个依赖的服务都分配⼀个线程池,当该线程池满了之后,直接拒绝,这样就防⽌某⼀个依赖的服务出问题阻塞了整个系统的其他服务
记录成功数、失败数、超时数以及拒绝数等指标
设置⼀个熔断器,将所有请求在⼀段时间内打到这个熔断器提供的⽅法上,触发条件可以是⼿动的,也可以根据失败率⾃动调整。
实时监控配置与属性的变更
当你启⽤ Hystrix 封装了原有的远程调⽤请求后,整个流程图变为下图所⽰。
接下来让我们学习如何使⽤它吧
快速⼊门
获取源码
maven
<dependency>
<groupId&flix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
网贴翻译<version&</version>
</dependency>
lvy
<dependency org="flix.hystrix" name="hystrix-core" rev="x.y.z" />
worked
如果你想下载 Jar 包⽽不是构建在⼀个⼯程⾥,如下
<?xml version="1.0"?>
<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd <modelVersion>4.0.0</modelVersion>
<groupId&flix.hystrix.download</groupId>
<artifactId>hystrix-download</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Simple POM to download hystrix-core and dependencies</name>
<url>/Netflix/Hystrix</url>
<dependencies>
油泵工作原理<dependency>
<groupId&flix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version&</version>
<scope/>
</dependency>
</dependencies>
</project>
然后执⾏
mvn -l dependency:copy-dependencies
Hello World
最简单的⽰例
public class CommandHelloWorld extends HystrixCommand<String> {
private final String name;
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}
@Override
protected String run() {
// a real example would do work like a network call here
return "Hello " + name + "!";
}
}
该 commond 类可以⽤以下⽅法使⽤
String s = new CommandHelloWorld("Bob").execute();
Future<String> s = new CommandHelloWorld("Bob").queue();
Obrvable<String> s = new CommandHelloWorld("Bob").obrve();
更多具体的⽤法详见如何使⽤模块
构建
下载源码并构建
$ git clone :Netflix/Hystrix.git
$ cd Hystrix/
$ ./gradlew build
或者像这样构建
$ ./gradlew clean build
构建的输出⼤概是这样的
$ ./gradlew build
:hystrix-core:compileJava
:hystrix-core:processResources UP-TO-DATE
:hystrix-core:class
:hystrix-core:jar
:hystrix-core:sourcesJar
:hystrix-core:signArchives SKIPPED
:
hystrix-core:asmble
peppapig:hystrix-core:licenMain UP-TO-DATE
:hystrix-core:licenTest UP-TO-DATE
:hystrix-core:compileTestJava
:hystrix-core:processTestResources UP-TO-DATE
:hystrix-core:testClass
:hystrix-core:test
:hystrix-core:check
:hystrix-core:build
:hystrix-examples:compileJava
:hystrix-examples:processResources UP-TO-DATE
:
hystrix-examples:class
:hystrix-examples:jar
:hystrix-examples:sourcesJar
:hystrix-examples:signArchives SKIPPED
:hystrix-examples:asmble
:hystrix-examples:licenMain UP-TO-DATE
vicente:hystrix-examples:licenTest UP-TO-DATE
:hystrix-examples:compileTestJava
:hystrix-examples:processTestResources UP-TO-DATE
:hystrix-examples:testClass
:hystrix-examples:test
:
hystrix-examples:checkachi
:hystrix-examples:build
BUILD SUCCESSFUL
Total time: 30.758 cs
clean build ⽅式的输出如下
> Building > :hystrix-core:test > 147 tests completed
⼯作原理
流程图
下图展⽰了当你⽤使⽤ Hystrix 封装后的客户端请求⼀个服务时的流程
1. 创建 HystrixCommand 或 HystrixObrvableCommand 对象
韩国老歌通过构建这两个对象来发起请求,构造函数中可以传⼊你发起请求时需要的参数如果你需要的是返回⼀个单独的响应,那你就⽤HystrixCommand 对象HystrixCommand command = new HystrixCommand(arg1, arg2);
⼊股你需要的是聚合起来的多个响应,就⽤HystrixObrvableCommand对象
HystrixObrvableCommand command = new HystrixObrvableCommand(arg1, arg2);
2. 执⾏ command
⼀共有四种⽅式可以执⾏ command,其中前两种⽅式都只适⽤于简单的 HystrixCommand 对象
excute() — 以阻塞⽅式运⾏,并返回返回其包装对象的响应值,或者抛出异常
queue() — 返回⼀个 Future 对象,你可以选择在适当时机 get
obrve() —
toObrvable() —
K value = ute();
泛读Future<K> fValue = command.queue();acup
Obrvable<K> ohValue = command.obrve(); //hot obrvable
Obrvable<K> ocValue = Obrvable(); //cold obrvable
实际上,同步⽅法 execute() 底层逻辑是调⽤ queue().get(),然后 queue() 实际上是调⽤了 toObrv
able().toBlocking().toFuture(),也就是说所有 HystrixCommand 的逻辑都是⾛ Obrvable 实现
3. 是否请求缓存
如果开启了请求缓存,并且该响应可以在缓存中找到,那就⽴刻返回缓存的响应值,⽽不会再⾛远程调⽤逻辑
4. 是否开启熔断
当执⾏ command 时,Hystrix 会判断熔断是否开启,如果是开启状态则⾛ (8) 进⾏ Fallback 降级策略,如果未开启则⾛ (5) ,继续下⼀步判断是否可以执⾏ command
5. 线程池\队列\信号量是否已满
如果上述三者已达到阈值,Hystrix 就会直接⾛ (8) 进⾏ Fallback 降级策略
6. struct() 或 HystrixCommand.run()
这段太难了,不太会翻译,⽇后有理解再补充
Here, Hystrix invokes the request to the dependency by means of the method you have written for th
is purpo, one of the following:
— returns a single respon or throws an exception
— returns an Obrvable that emits the respon(s) or nds an onError notification
If the run() or construct() method exceeds the command’s timeout value, the thread will throw a TimeoutException (or a parate timer thread will, if the command itlf is not running in its own thread). In that ca Hystrix routes the respon through 8. Get the Fallback, and it discards the eventual return value run() or construct() method if that method does not cancel/interrupt.
Plea note that there's no way to force the latent thread to stop work - the best Hystrix can do on the JVM is to throw it an InterruptedException. If the work wrapped by Hystrix does not respect InterruptedExceptions, the thread in the Hystrix thread pool will continue its work, though the client already received a TimeoutException.
This behavior can saturate the Hystrix thread pool, though the load is 'correctly shed'. Most Java HTTP client libraries do not interpret InterruptedExceptions. So make sure to correctly configure connection and read/write timeouts on the HTTP clients.
If the command did not throw any exceptions and it returned a respon, Hystrix returns this respon after it performs some some logging and metrics reporting. In the ca of run(), Hystrix returns an Obrvable that emits the single respon and then makes an onCompleted notification; in the ca of construct() Hystrix returns the same Obrvable returned by construct().
时序图
熔断器
隔离机制
线程与线程池
请求合并
缓存
如何使⽤
Hello World
HystrixCommand 实现
public class CommandHelloWorld extends HystrixCommand<String> {
private final String name;
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}
@Override
protected String run() {
// a real example would do work like a network call here
return"Hello " + name + "!";
}
}
HystrixObrvableCommand 实现
public class CommandHelloWorld extends HystrixObrvableCommand<String> {
private final String name;
public CommandHelloWorld(String name) {