搞定Spring Cloud断路器组件 Hystrix 的舱壁模式

在构建分布式应用的时候,断路器保护是不得不考虑的问题,主要是防止因为某一个服务超时而导致整个分布式系统的雪崩效应。防止这种情况发生,常用的有三种方式:负载均衡(Robbin、Fegin)、后背模式(Hystrix)和舱壁模式(Hystrix)。Spring Cloud提供了专业的断路器组件 Hystrix,今天我们就来看下Hystrix的舱壁模式。

搞定Spring Cloud断路器组件 Hystrix 的舱壁模式

 

一、啥是舱壁模式

舱壁模式(Bulkhead)隔离了每个工作负载或服务的关键资源,如连接池、内存和CPU。使用舱壁避免了单个工作负载(或服务)消耗掉所有资源,从而导致其他服务出现故障的场景。这种模式主要是通过防止由一个服务引起的级联故障来增加系统的弹性。

通过应用舱壁模式,可以保护有限的资源不被耗尽。

二、Hystrix 共享线程池

Hystrix默认情况下是共享线程池,适用于服务调用比较小的情况。

调用默认是使用相同的线程来执行调用的,这些线程Java容器为处理所有请求预留的。在高服务器请求的情况下,一个性能较低的服务会“霸占”java容器中绝大多数线程,而其它性能正常的服务的请求则需要等待线程资源的释放。最后,整个java容器会崩溃。舱壁模式能将远程调用隔离在各个远程调用自己的线程池中,因此单个性能出问题的服务能得到控制,java容器也不会崩溃。

Hystrix将远程服务的请求托管在一个线程池中。即默认情况下,所有Hystrix命令(@HystrixCommand)共享同一个线程池来处理这些请求。该线程池中持有10个线程来处理各种远程服务请求,可以是REST服务调用、数据库访问等。

搞定Spring Cloud断路器组件 Hystrix 的舱壁模式

 

三、Hystrix 隔离的线程池

@HystrixCommand的默认配置适用于只有少量远程调用的应用。幸运的是,Hystrix提供了简单易用的方法实现舱壁来隔离不同的远程资源调用。下图说明了Hystrix将不同的远程调用隔离在不同的“舱室”(线程池)中。

搞定Spring Cloud断路器组件 Hystrix 的舱壁模式

 

实现这种隔离的线程池,需要使用到@HystrixCommand注解提供的其他属性。这样实现,

  • 为方法getLicensesByOrg()设置一个隔离的线程池
  • 设置该线程池的线程数
  • 设置队列的容量,该队列的作用是当线程池中的线程都处于工作状态,接下来的请求会进入该队列。
@HystrixCommand(
 fallbackMethod = "buildFallbackLicenseList",
 threadPoolKey = "licenseByOrgThreadPool",
 threadPoolProperties = {
 @HystrixProperty(name = "coreSize",value="30"),
 @HystrixProperty(name="maxQueueSize", value="10")
 }
)
public List<License> getLicensesByOrg(String organizationId){
 randomlyRunLong();
 return licenseRepository.findByOrganizationId(organizationId);
}

上面代码中涉及到几个新的@HystrixCommand暴露的属性。第一个是threadPoolKey,这对于Hystrix来说是新建一个线程池的信号,threadPoolKey的值则是线程池的标识。如果只是配置了threadPoolKey,那么Hystrix会使用默认配置来初始化该线程池。

而若要自定义新建的线程池,则需要使用另一个属性:threadPoolProperties。该属性接收一个@HystrixProperty数组,这些HystrixProperty就是用来配置新建的线程池。比如,可以使用coreSize来配置线程池的容量。

当然也可以设置一个队列,来应对当线程池繁忙的情况。通过maxQueueSize来设置该队列的容量。当请求的数量超过队列的容量,其它的请求会迅速失败返回,直到队列又有空闲的“位置”。

对于属性maxQueueSize,有亮点需要注意。第一,如果value值设置为-1,Hystrix会使用SynchronousQueue来实现该队列。同步队列意味着,当线程池繁忙时,就不再接收其它请求,直接迅速失败返回,可以粗略理解为该队列不存在。当设置一个大于1的值时,Hystrix会创建一个LinkedBlockingQueue,这样会让后到的请求排队等候线程池的线程完成请求处理。第二,Hystrix允许我们使用SizeRejectionThreshold属性来动态变更队列的容量,但该属性只有在maxQueueSize的value值大于0的时候才能生效。而maxQueueSize属性的值只能在线程池初始化时设置,所以当maxQueueSize为-1时,将无法再变更队列的容量,因为队列是同步队列。

搞定Spring Cloud断路器组件 Hystrix 的舱壁模式

 

四、Netflix建议的线程池容量

Netflix建议:

每秒处理请求的峰值 × 99%平均响应时间 + 缓冲线程数

但是,在服务正式部署之前,我们是无法知道服务的性能为几何。这里有一个指标可以作为参考,当目标远程资源正常的情况下,调用还会出现超时,那么线程池的容量就需要调整了。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值