目录
Hystrix
解决什么问题
分布式微服务系统以来很多子服务,每个子系统都可能出现故障和错误,如果服务不相互隔离,那么每个服务的错误都可能压垮其他服务,导致服务雪崩。
假设每个服务的可用性为9999,那么30个子服务的整体可用性为
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.
hystrix的方案和设计原则
- 熔断器模式和设置超时时间,防止任何单一依赖关系耗尽所有容器(如Tomcat)用户线程。
- 减少负载和快速失败,而不是排队,每个服务设置线程池或者信号量隔离,满了直接拒绝而不是排队
- 异常回退机制,在可行的情况下提供后备方案,以保护用户不发生故障。
- 命令模式,使用隔离技术(如断路器模式)来限制任何一个依赖的影响。
- 监控和统计调用信息,优化故障发现时间,通过接近实时的度量、监视和报警。
- 动态配置修改,优化故障恢复时间,通过配置实时的配置修改生效
原理解析
hystrix流程图
Maven集成
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.12</version>
</dependency>
基本使用代码
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 + "!";
}
}
command执行
- execute() — 阻塞式调用command,
execute()
调用queue().get()
. - queue() —异步调用
queue()
调用toObservable().toBlocking().toFuture()
. - observe() — 调用toObservable()后直接订阅,hystrix的核心调用流程都是基于rxjava实现的,关于observable的使用,可以参考rxjava的文档,后面将专门介绍rxjava的原理和使用。
- toObservable() —只变成observable对象不订阅,需要等调用方订阅后生效,可以看到以上几种方法都是基于这个方法实现的。
requestcache
是请求上下文作用域的,需要初始化contxt
HystrixRequestContext context = HystrixRequestContext.initializeContext();
and then this at the end of the request:
context.shutdown();
断路器开关
如果错误率达到阈值会将断路器打开,请求直接返回异常走fallback
断路器会通过所有command的metrics信息,失败率,超时率等信息,进行自动开发和关闭。Metrics信息是按照桶统计的,每个桶代表一段时间,通过配置固定桶的个数,通过滑动时间窗口实现统计固定时间窗口的统计信息。
hystrix隔离
使用线程池或者信号量进行,如果达到信号量阈值或者线程池满了就直接拒绝走fallback逻辑
线程池和信号量隔离区别:
- 线程池
- 不会阻塞调用线程,如tomcat
- 可以实现异步调用或者并发调用
- 带来线程切换开销
- 请求排队时延,队列大小尽量接近0
- 线程池的配置问题:p99.5th耗时*qps
- 信号量
- 基于javasemaphore,消耗低
- 只能限制并发量,在调用线程执行,会阻塞调用方
fallback
执行command的run方法,成功则返回结果,失败则调用fallback逻辑,fallback执行失败的话返回异常给调用线程
- 业务层面中断任务执行,在底层是否中断是不确定的,hystrix只能抛出interuptexception,是否能中断线程执行要看执行任务的线程是否响应intteruptexception异常,如果不响应是不会释放线程。
- Fallback可以执行返回null,默认值,输出日志,告警,调用降级服务等操作,不要抛出异常
- Fallback可以执行忽略异常: ignoreExceptions属性,使用这个配置,如果抛出被配置的异常,不会被统计到异常metrics中,直接返回badrequest异常
- hystrix基于 RxJava
onErrorResumeNext
操作符无缝的实现原始observable和fallback observable之间的传递和变换