SpringCloud与Hystrix集成踩坑-线程模型

项目中使用微服务架构一两年的时间,在这期间使用到了SpringCloud与Netflex-Hystrix断路器,实际使用过程中踩了不少的坑,在此记录

Tomcat线程模型

  1. HTTP请求在进入服务端后,会首先进入tomcat的Accept队列等待后续处理
  2. tomcat内的Acceptor线程不断的从Accept队列中取出连接,并将请求转移到Worker线程来做后续业务处理,如果此时worker线程不足,则Acceptor线程将阻塞
  3. worker线程执行原生webfilter过滤器逻辑
  4. worker线程执行Spring的DispatcherServlet逻辑

可见,服务端最大并发能力由worker线程数决定,Tomcat默认的最小worker线程数为10,最大为200,而Acceptor队列最大容量在window下是8192,linux下是10000

引入Hystrix后的线程模型

springcloud-hystrix断路器的介入是在请求进入DispatcherServlet以后,有线程池模式和信号量模式两种,默认为线程池模式

  1. worker线程在DispatcherServlet内部会获取hystrix线程来执行后续的逻辑,如果没有足够的线程来处理,则会进入hystrix队列等待
  2. 在hystrix线程处理或队列等待的过程中,worker线程将被阻塞,直到hystrix完成处理

tomcat分配的worker处理线程看其名字http-nio-8080-exec-1像是NIO,实际上tomcat线程只有在HTTP请求头的读写部分为nio,其他部分均为bio,在请求进入hystrix后,worker线程无法实现复用

hystrix线程池有以下几项配置,分别是

hystrix:
  threadpool:
    default:
      coreSize: 10      #Hystrix核心线程数,默认10
      maximumSize: 20   #Hystrix最大线程数,默认10,只有在设置allowMaximumSizeToDivergeFromCoreSize=true后才能生效
      allowMaximumSizeToDivergeFromCoreSize: true   #是否允许线程数动态调整,默认false
      keepAliveTimeMinutes: 1   #非核心线程空闲多久后自动释放(单位分钟)
      maxQueueSize: 10      #请求等待队列排队请求最大容量,默认-1为无容量,即不允许排队等待而直接降级/抛出异常
      queueSizeRejectionThreshold: 5 #请求等待队列中的排队请求数达到此值后,请求将被降级/抛出异常,默认5,建议同时调整maxQueueSize值,若maxQueueSize=-1,则此属性不可用

通过以上流程我们能够发现一些特点

  • 之所以要分maxQueueSize和queueSizeRejectionThreshold这两个参数,而不是直接使用maxQueueSize,是因为队列一旦创建就不可以改变大小,无法实现动态调整,所以才有了第二个参数,没有其他意义
  • 在引入hystrix后,服务端的最大并发能力仍然受到tomcat的worker线程数限制,即hystrix总可用线程数+hystrix队列最大容量不可能超过tomcat的worker线程数
  • 原生webfilter的执行是在进入hystrix之前的worker线程,而后续任务的执行在hystrix,故若程序在webfilter中写入了ThreadLocal数据,在后续逻辑中无法读取,会造成程序BUG
  • hystrix线程在工作的过程中,对应的worker线程将被阻塞,造成了线程的浪费,这个问题在当前模式下无法解决

Hystrix线程池与Tomcat线程池工作方式的不同

Tomcat线程池是web容器自身实现的,非java的默认线程池,有min-spare与max的配置,分别代表最小线程数和最大线程数,在请求进入后,线程池当前线程数如果没有达到min-spare,会创建新的线程,而如果并发请求数超过了min-spare,未达到max,则会继续动态创建线程(在空闲后会收缩),只有在并发请求达到max后,后续请求才会在队列中持续等待

默认Hystrix执行线程池为java的ThreadPoolExecutor,它不像Tomcat一样尽可能的创建线程,而是在请求并发数超过coreSize后,优先进入hystrix队列等待,只有在队列满了之后才会创建新的线程

Hystrix的信号量模式

上面说的都是hystrix默认的线程池模式的情况,而在hystrix信号量模式下,hystrix不会创建自己的线程池和队列,而是采用信号量的方式直接对tomcat线程进行隔离,故可以节省一半的线程数,并且不会出现线程池模式的webfilter的ThreadLocal问题,但是他的问题在于

  • 无法使用hystrix队列,所以达到并发限制后请求将直接被降级/抛出异常
  • 无法提供hystrix超时控制,一旦任务阻塞将无法实现断路器的熔断能力

 

以上是在使用hystrix时踩的其中一个小坑,下一篇文章将提供hystrix线程池工作方式问题的解决方案,点此查看

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值