# 105. 生产环境中的线程池大小以及 timeout 超时时长优化经验总结

在生产环境里面,一个线程池的大小和 timeout 时长怎么设置?如果设置不合理问题还是很大的

# 优化配置流程

有两种方案:

  1. 一上来就设置大一点,然后再逐步优化降低
  2. 一上来就默认配置,然后再逐步优化

这里讲解使用默认值方式,再逐步优化的流程

  1. 一开始先不要设置 tomeout 超时时长,默认就是 1000ms(1s)

  2. 一开始先不要设置线程池大小,默认就是 10

  3. 直接部署到生产环境,如果运行良好,那么就不用管了

  4. 依赖标准的监控和报警机制来捕获到系统的异常运行情况(观察 24 小时)

  5. 根据调用延迟的占比、流量来计算出让断路器生效的最小配置数值

  6. 可以通过 hystrix 配置进行热修改,然后继续在 hystrix dashboard 上监控

    监控在后面章节会讲解,但是这个热修改不知道后面有没有, 前面的章节热修改只提到过等待队列的热修改,但是还有限制。

通过以上步骤循环观察,知道调优到最佳

# 优化经验

假设对一个依赖服务的高峰调用 QPS 是每秒 30 次

  • 默认线程池大小为 10 每秒高峰访问次数 * 99% 的访问延时 + 队列 buffer = 30 * 0.2 + 4 = 10 线程

    也就是说,99 % 的访问都在 200 毫秒(0.2 秒)内响应;每个线程 1 秒钟处理 3 个线程;

    3 * 200 = 600 毫秒;但是别忘记了,还有队列中等待的时间,一个线程先执行,最后一个线程最长会等待 400 毫秒时间

  • 超时时间:按照 99.5% 的访问延时时间进行设置

    一次访问 200 毫秒内响应(TP99 如果是 200 ms),再加一次重试时间,为 300 毫秒

    疑问:那么理想的超时时间是 400 毫秒(上面已经说过,加上等待时间),但是这里感觉又不对, 假如是 400 毫秒,都超时那么低三个线程将会超过 1 秒钟,导致 1 秒钟内处理不了 3 个线程。 下一秒就会有另外的 30 个线程进来,就会导致线程池已满,部分线程就直接被 reject 了

    所以这第一步计算线程公司是不是就有问题?

总之,这里的意思就是要让 1 秒内所有的线程都能执行完,根据并发计算到的数量;

那么线程大小和超时时间能导致什么情况出现呢?如下图

左侧为 tomcat 容器线程,右侧为 hystrix 线程池,如果设置的不合理, 将导致大量线程被阻塞在 hystrix 上,也就间接导致 tomcat 的线程被阻塞住, 这样就会导致 tomcat 没有更多的资源去处理其他的服务调用;

如果设置得合理,就算这个服务调用比较耗时,那么也只是这个服务被降级的多,很快就返回了, 并不会影响其他的服务资源调用

大家可能会想,每秒的高峰访问次数是 30 次,如果是 300 次,甚至是 3000 次、30000次呢? 30000 * 0.2 = 6000 + buffer = 6100,一个服务器内一个线程池给 6000 个线程, 这很恐怖的,如果你一个依赖服务占据的线程数量太多的话,会导致其他的依赖服务对应的线程池里没有资源可以用了, 因为一个 tomcat 总的并发数量是有限的。

那么在这种情况下,其实就需要更多的机器来支撑了。

你要真的说是,你的公司服务的用户量,或者数据量,或者请求量,真要是到了每秒几万的QPS,

30000QPS:60 * 3 = 1分钟 180万 访问量,一小时就按 1 亿计算,这个就很大了的量了; 用几十台服务器去支撑,我觉得很正常,一般 QPS 每秒在几千都算多的了