资源隔离、限流、降级、熔断、实时监控
设计原则:
- 对依赖服务调用时出现的延迟和失败进行控制和容错
- 在复杂的分布式系统中,阻止某一个依赖服务的故障在整个系统中蔓延
- 提供fail-fast(快速失败)和快速恢复的支持
- 提供fallback优雅降级的支持
- 支持近实时的监控、报警及运维操作
细节:
- 阻止任何一个依赖服务耗尽所有的资源,比如tomcat中的所有线程资源
- 避免请求排队和积压,采用限流和fail fast来控制故障
- 提供fallback降级机制来应对故障
- 使用资源隔离技术,比如bulkhead(舱壁隔离技术)、swimlane(泳道技术)、circuit breaker(短路技术),来限制任何一个依赖服务的影响
- 通过近实时的统计/监控/报警功能,来提高故障发现的速度
- 通过近实时的属性和配置热修改功能,来提高故障处理和恢复的速度
- 保护依赖服务调用的所有故障情况,而不仅仅只是网络故障情况
实现:
- 通过HystrixCommand(一条数据)或者HystrixObservableCommand(多条数据)来封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中,资源隔离
- 对于超出我们设定阀值的服务调用,直接进行超时,不允许其耗费过长的时间阻塞住,这个超时时间默认是99.5%的访问时间,但一般我们可以自己设置下
- 为每一个依赖服务维护一个独立的线程池(默认是10个线程),或者是semaphore,当线程池已满时,直接拒绝对这个服务的调用
- 对依赖服务调用的成功次数、失败次数、拒绝次数、超时次数进行统计
- 如果对一个依赖服务的调用失败次数超过了一定的阀值,自动进行熔断,在一定的时间内对该服务的调用直接降级,一段时间后再自动尝试恢复
- 当一个服务调用出现失败、被拒绝、超时、短路等异常情况时,自动调用fallback降级机制
- 对属性和配置的修改提供近实时的支持
资源隔离
- 线程池隔离和信号量(semaphore)隔离区别
- 线程池隔离使用的是自己内部的线程处理请求,对自己的线程可以控制,可以捕获timeout,信号量是控制请求服务的总线程量,没有自己的线程
- 信号量一般用来缓存服务,将部分特别少,访问又特别频繁的一些数据,放在自己的纯内存中,这种直接访问本地内存的逻辑比较适合信号量隔离
- Command名称和Command Group和Command Threadpool
- Command名称默认是类名,Command group用来定义线程池Command Threadpool的,如果指定了Pool Key,则同一个Group的不同Command会请求指定的线程池
八大步骤及原理
-
创建Command
- HystrixCommand用于仅仅会返回一个结果的调用
- HystrixObservableCommand主要用于可能会返回多条结果的调用
-
调用Command
- 执行Command就可以发起一次对依赖服务的调用
- HystrixCommand调用 同步:
execute()、异步:queue(),HystrixObservableCommand调用 同步:observe()、异步toObservable()
-
检查是否开启缓存
- 如果开启缓存会从缓存找request cache返回结果
-
检查是否开启了短路器
- 如果开启了,直接进行fallback降级处理
-
检查线程池/队列/semaphore是否已经满了
- 满了就直接进行fallback降级处理
-
执行Command
- timeout抛出异常,进行fallback降级处理
- 报错,进行fallback降级处理
-
短路健康检查
将每一个依赖服务的成功、失败、拒绝、超时等事件发送给circuit breaker断路器
短路器会对调用的成功、失败、拒绝、超时等事件次数进行统计
短路器会根据这些次数来决定是否短路,如果开启短路,一段时间内就会直接短路,下一次检查发现调用成功了,关闭短路器
调用fallback降级机制