用Hystrix保护自己
Posted 要师傅talk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Hystrix保护自己相关的知识,希望对你有一定的参考价值。
服务的稳定是公司可持续发展的重要基石,随着业务量的快速发展,一些平时正常运行的服务,会出现各种突发状况,而且在分布式系统中,每个服务本身又存在很多不可控的因素,比如线程池处理缓慢,导致请求超时,资源不足,导致请求被拒绝,又甚至直接服务不可用、宕机、数据库挂了、缓存挂了、消息系统挂了…
网络通信不可靠
三态(成功、失败、未知)
时钟不可靠
协调困难
无法感知崩溃和超时
CAP/拜占庭
常见事故现场
成功,失败,异常,超时,重试,短路,限流,削峰,幂等性,队列打满,内存溢出,缓存打穿,丢数据,修数据,应用雪崩……
永远不要相信你的上下游
搞清楚你使用的工具原理
关注业界最佳实践
任何复杂问题都可以通过引入一个间接层来解决
理解client的运行机制
在理解上下游的机制后合理设置自己的超时时间
Failover,Failsafe,Failfast,Failback,Forking
熔断降级
限流(限总量、限速率、限并发)
异步化/队列
依赖的服务出现延迟或失败的时候,提供保护和控制
分布式系统中,防止级联失败
Failfast,让系统快速恢复
Failback,提供失败回退优雅降级机制
熔断器设计模式的可靠实现
提供近实时的监控、报警和运维控制机制
下面将更详细的解析每一个步骤都发生哪些动作:
1. 构建一个HystrixCommand
或者HystrixObservableCommand
对象。
第一步就是构建一个HystrixCommand
或者HystrixObservableCommand
对象,该对象将代表你的一个依赖请求,向构造函数中传入请求依赖所需要的参数。
如果构建HystrixCommand
中的依赖返回单个响应,例如:
HystrixCommand command = new HystrixCommand(arg1, arg2);
如果依赖需要返回一个Observable来发射响应,就需要通过构建HystrixObservableCommand对象来完成,例如:
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);
2. 执行命令
有4种方式可以执行一个Hystrix命令。
1) execute()
—该方法是阻塞的,从依赖请求中接收到单个响应(或者出错时抛出异常)。
2) queue()
—从依赖请求中返回一个包含单个响应的Future对象。
3) observe()
—订阅一个从依赖请求中返回的代表响应的Observable对象。
4) toObservable()
—返回一个Observable对象,只有当你订阅它时,它才会执行Hystrix命令并发射响应。
K value = command.execute();
Future<K> fValue = command.queue();
Observable<K> ohValue = command.observe(); //hot observable
Observable<K> ocValue = command.toObservable(); //cold observable
同步调用方法execute()
实际上就是调用queue().get()
方法,queue()
方法的调用的是toObservable().toBlocking().toFuture()
.也就是说,最终每一个HystrixCommand都是通过Observable来实现的,即使这些命令仅仅是返回一个简单的单个值。
3. 响应是否被缓存
如果这个命令的请求缓存已经开启,并且本次请求的响应已经存在于缓存中,那么就会立即返回一个包含缓存响应的Observable
。
4. 回路器是否打开
当命令执行执行时,Hystrix会检查回路器是否被打开。
如果回路器被打开(或者tripped),那么Hystrix就不会再执行命名,而是直接路由到第8
步,获取fallback方法,并执行fallback逻辑。
如果回路器关闭,那么将进入第5
步,检查是否有足够的容量来执行任务。(其中容量包括线程池的容量,队列的容量等等)。
5. 线程池、队列、信号量是否已满
如果与该命令相关的线程池或者队列已经满了,那么Hystrix就不会再执行命令,而是立即跳到第8
步,执行fallback逻辑。
6. HystrixObservableCommand.construct() or HystrixCommand.run()
在这里,Hystrix通过为此目的编写的方法(以下之一)调用对依赖项的请求:
- HystrixCommand.run()
—返回单个响应或引发异常
- HystrixObservableCommand.construct()
—返回一个Observable,它发出响应或发送onError通知
7. 计算回路指标[Circuit Health]
Hystrix会报告成功、失败、拒绝和超时的指标给回路器,回路器包含了一系列的滑动窗口数据,并通过该数据进行统计。
它使用这些统计数据来决定回路器是否应该熔断,如果需要熔断,将在一定的时间内不在请求依赖[短路请求],当再一次检查请求的健康的话会重新关闭回路器。
8. 获取FallBack
当命令执行失败时,Hystrix会尝试执行自定义的Fallback逻辑:
1) 当construct()或者run()方法执行过程中抛出异常。
2) 当回路器打开,命令的执行进入了熔断状态。
3) 当命令执行的线程池和队列或者信号量已经满容。
4) 命令执行超时。
9. 返回成功的Response
如果Hystrix命令成功执行,它将以Observable
的形式将一个或多个响应返回给调用方。
根据您在上面的步骤2
中调用命令的方式,此Observable
可能会在返回给您之前进行转换
• 线程池隔离机制,⽤于IO依赖,⽹络请求
• 信号量隔离,⽤于应⽤内部的并发控制
类型 | 优点 | 不足 | 适用 |
---|---|---|---|
线程 | 支持排队和超时、支持异步调用 | 线程调用和切换产生额外开销 | 不受信客户(比如三方服务稳定性是无法推测的) |
信号量 | 轻量且无额外开销 | 不支持任务排队和超时,不支持异步 | 受信客户、高频高速调用服务(网关、cache) |
配置spring-cloud-starter-netflix-hystrix
添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
然后在Application类上增加@EnableHystrix
来启用Hystrix starter:
public class ProviderApplication {
配置Provider端
在Dubbo的Provider上增加@HystrixCommand
配置,这样子调用就会经过Hystrix代理。
public class HelloServiceImpl implements HelloService {
(commandProperties = {
"circuitBreaker.requestVolumeThreshold", value = "10"), //窗口期内, 失败10次断路器打开 (name =
"circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //断路器5s恢复, 默认10s (name =
"circuitBreaker.errorThresholdPercentage", value = "10"), //出错百分比阈值, 当达到此阈值后, 开始短路. 默认 50% (name =
"execution.isolation.thread.timeoutInMilliseconds", value = "2000") //超时时间为2s (name =
})
public String sayHello(String name) {
// System.out.println("async provider received: " + name);
// return "annotation: hello, " + name;
throw new RuntimeException("Exception to show hystrix enabled.");
}
}
配置Consumer端
对于Consumer端,则可以增加一层method调用,并在method上配置@HystrixCommand
。当调用出错时,会走到fallbackMethod = "reliable"
的调用里。
private HelloService demoService;
"reliable") (fallbackMethod =
public String doSayHello(String name) {
return demoService.sayHello(name);
}
public String reliable(String name) {
return "hystrix fallback value";
}
上述配置实际运行效果:
Hystrix除了实现容错之外,还提供了近乎实时的监控。Hystrix Command和HystrixObservableCommand在执行时,会会生成执行结果和运行指标,比如每秒的请求数和成功数等,这些监控数据对于分析系统请求的调用情况很有用。
下图是Hystrix运行时可以监控的维度、指标
最后
啰嗦了一大堆,从代码看,些许有些侵入性,但是毫无副作用。
在实际场景中,合理利用熔断器,针对不同粒度(服务/接口),我们会降低”修数据、三方服务挂了……“带来的困扰,提升服务质量。
以上是关于用Hystrix保护自己的主要内容,如果未能解决你的问题,请参考以下文章
springcloud报错-------关于 hystrix 的异常 FallbackDefinitionException:fallback method wasn't found(代码片段