前言:
在微服务项目中,各个微服务相互调用,如果服务的服务接口异常、网络延迟、或高并发下某个节点被阻塞而导致整个服务的资源耗尽,这样就可能会导致整个服务资源耗尽,出现服务雪崩现象,对于这种情况我们可以使用 Hystrix、Sentinel 组件来进行限流熔断,避免服务雪崩,本篇我们主要介绍一下 Hystrix 的隔离策略。
Hystrix 的隔离策略
熟悉 Hystrix 的都知道 Hystrix 有两种隔离策略,分别是线程池隔离和信号量隔离,具体如下:
- 线程池隔离(THREAD):线程池隔离,HystrixCommand 将会在单独的线程上执行,即每个实例都增加个线程池进行隔离,并发请求受线程池中线程数量的限制(默认10),线程池隔离是 Hysrix 的默认隔离策略。
- 信号量隔离(SEMAPHORE):信号量隔离,HystrixCommand 将会在调用线程上执行,开销相对较小,并发请求受信号量的个数的限制(默认10),因为是同步的请求,不支持超时,只能依靠协议本身。
线程池隔离
官网描述如下:
it executes on a separate thread and concurrent requests are limited by the number of threads in the thread-pool
它在一个单独的线程上执行,并发请求受到线程池中线程数量的限制。
通过线程池实现隔离,每个请求都会在线程池中开启一个新的线程,即每个隔离粒度都是个线程池,互相不干扰,线程池隔离,可以通过hytrix 直接设置超时。
线程池隔离是 Hystrix 的默认隔离策略,也是推荐方式,使用线程池隔离,每一个依赖服务调用都在一个单独的线程中执行,这个线程从专门为每个 Hystrix 命令或服务依赖配置的线程池中获取,如果果线程池已满,新的请求将会被立即拒绝,不会继续等待或阻塞调用者线程。
线程池隔离的优点:
- 提供了真正的任务隔离;如果依赖服务变得缓慢或无响应,只会会影响到运行在同一个线程池中的请求。
- 可以限制并发调用的数量,避免系统过载,可以通过 hytrix 直接设置超时,超时后直接返回。
线程池隔离
官网描述如下:
it executes on the calling thread and concurrent requests are limited by the semaphore count
它在调用线程上执行,并发请求受到信号量计数的限制。
就是每次发起 Feign 调用的时候,使用调用者线程执行请求(线程池隔离是使用线程池的线程执行请求),对请求进行计数,当请求数量大于最大请求数量的时候,会调用 FallBack 接口快速返回失败。
因为使用调用者线程执行 Feign 请求,因此信号量的调用方式是同步的,同步调用只能等到调用结果返回,无法对访问设置超时,只能依靠调用协议超时,无法主动释放。
信号量隔离的优点:
- 开销较小,没有线程创建和切换的成本。
- 适用于执行非常快但需要频繁访问的操作。
适用场景:
- 线程池隔离:使用绝大多数场景,尤其是外部调用的场景,尤其是那些可能会最或失败的服务(如外部API、数据库访问等)。
- 信号量隔离:适合轻量级操作,不太可能导致长时间延迟的服务调用,如内存或缓存服务访问。
Hystrix 信号量隔离适用场景官网建议如下:
Generally the only time you should use semaphore isolation for HystrixCommands is when the call is so high volume (hundreds per second, per instance) that the overhead of separate threads is too high; this typically only applies to non-network calls
一般来说,只有当调用的容量非常大(每个实例每秒数百个),导致单独线程的开销太高时,才应该对 HystrixCommands 使用信号量隔离,这通常只适用于非网络调用。
如有不正确的地方请各位指出纠正。