在部署 web 应用到生产环境,或者在对 web 应用进行性能测试的时候,经常会有人问:如何决定 web 应用线程池大小?决定一个 IO 阻塞型 web 应用的线程池大小是一项很艰巨的任务。通常是通过进行大量的性能测试来完成。在一个 web 应用中同时拥有多个线程池会让决定最优线程池大小的过程变得更加复杂。本文将就这个常见的问题进行一些讨论和建议。

线程池

web 应用中的线程池大小决定了在指定时间内能够处理的并发请求数。如果一个 web 应用接收到的请求数高于线程池大小,多出来的请求将进入队列等待,或被拒绝。

请注意并发和并行不是一个概念。并发请求指的是正在处理中的请求数量,在某个时间点,只有其中的一小部分能够得到 CPU 执行。而并行请求指的是正在处理的请求数量,在某个时间点,所有请求都在被 CPU 执行。

在非阻塞型 IO 应用中,比如 NodeJS,单个线程(进程)能够同时处理多个请求。多核 CPU 处理器下,通过增加线程或进程数能够处理并行请求。

在阻塞型 IO 应用中,比如 SpringMVC,单个线程只能同时处理一个请求。要同时处理多个并发请求的话,我们必须增加线程数量。

计算密集型应用

在计算密集型应用中,线程池的大小应该等同于主机中 CPU 的数量。再添加更多线程将会打断请求的处理,因为线程的上下文切换也会延迟响应时间。

非阻塞型 IO 应用将会是 CPU 密集型的,因为在请求得到处理的时候没有线程等待时间。

IO 等待应用

决定 IO 等待应用的线程池大小会由于依赖于下游系统的响应时间而变得更加复杂,因为一个线程在其他系统响应之前始终是阻塞的。我们不得不像《应答者模式:I/O 阻塞型应用》中讨论的那样去增加线程的数量以提高 CPU 利用率。

利特尔法则

利特尔法则应用于非技术领域,比如银行,以估算处理进入银行客户所需要的银行出纳柜台的数量。

利特尔法则:在一个稳定的系统中,长时间观察到的平均顾客数量 L,等于长时间观察到的有效到达速率,λ,与平均每个顾客在系统中花费的时间之乘积:L = λW。

适用于 web 应用的利特尔法则:一个系统中线程的平均数量(Threads),等于 web 请求的到达速率(WebRequests per sec),与平均每个处理的响应时间(ResponseTime)的乘积。

Threads = 线程的数量

WebRequests per sec = 一秒内能够处理的 web 请求数

ResponseTime = 处理一次 web 请求所需要的时间

Threads = (WebRequests/sec) X ResponseTime

尽管上边这个公式提供了处理进入请求的线程个数,它并没有提供线程数和 CPU 核心数之间的比率信息,比如一个 x 个 CPU 的主机需要分配多少个线程。

测试决定线程池大小

要找出合适的线程池大小,需要在吞吐量和响应时间之间进行权衡。先以一个最小值开始测试:一个 CPU 一个线程(也就是线程池大小 = CPU 个数),应用线程池大小与下游系统平均响应时间成正比增长,直到 CPU 使用率饱和或者响应时间开始退化为止。

下图指出了请求数、CPU 以及响应时间等指标之间的关联关系。

CPU Vs 请求数演示了在增加 web 应用负载时的 CPU 利用率。

响应时间 Vs 请求数图演示了增加 web 应用负载对响应时间的影响。

绿点指出了最佳吞吐量和响应时间。

线程池大小 = CPU 个数



上图描述的是 IO 等待型应用在线程数等于 CPU 数时的情况。应用的线程在等待下游系统响应时发生了阻塞。由于线程都阻塞住了,系统响应时间因请求进入等待队列而被拉长。由于所有线程都处于阻塞状态,应用开始拒绝请求,尽管 CPU 使用率还很低。

线程池很大



上图描述的是 IO 等待型应用在 web 应用中创建了很多线程的情况。由于有很多数量的线程,线程的上下文切换将会很频繁。由于不必要的线程上下文切换,尽管吞吐量还没升上去的时候应用的 CPU 使用率就已经很高了。响应时间由于被请求的处理被线程的上下文切换所打断而被拉长。

最佳线程池大小



上图描述的是 IO 等待型应用在 web 应用中创建了合理数量的线程的情况。CPU 得到了有效利用,具备良好的吞吐量和较少的线程上下文切换。我们可以看到由于更少的打断(上下文切换),请求处理更加有效,应用有一个良好的响应时间。

线程池隔离

对于大多数 web 应用而言,只有少数几种类型的 web 请求会花费比较长的处理时间。这些慢的请求处理可能会拖累所有线程,并降低整个应用的性能。

处理这种问题的两个方案是:

为慢处理的 web 请求设置在一台独立的主机;

在同一个应用中为慢处理的 web 请求分配一个独立的线程池;

决定一个 IO 阻塞型 web 应用的线程池大小是一项很艰巨的任务。通常是通过进行大量的性能测试来完成。在一个 web 应用中同时拥有多个线程池会让决定最优线程池大小的过程变得更加复杂。

原文链接:http://venkateshcm.com/2014/05/How-To-Determine-Web-Applications-Thread-Poll-Size/。

如何决定 Web 应用的线程池大小的更多相关文章

  1. 如何决定Web应用的线程池大小

    线程池(Thread Pool)在Web应用中线程池的大小决定了在任何一个时间点应用可以处理请求的并发数.如果一个系统收到的请求数超过了线程池的大小,那么超出的请求要么进入等待队列要么被拒绝.请注意, ...

  2. 线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事

    线程池应该设置多少线程合适,怎么样估算出来.最近接触到一些相关资料,现作如下总结. 最开始接触线程池的时候,没有想到就仅仅是设置一个线程池的大小居然还有这么多的学问,汗颜啊. 首先,需要考虑到线程池所 ...

  3. 如何计算tomcat线程池大小?

    背景 在我们的日常开发中都涉及到使用tomcat做为服务器,但是我们该设置多大的线程池呢?以及根据什么原则来设计这个线程池呢? 接下来,我将介绍本人是怎么设计以及计算的. 目标 确定tomcat服务器 ...

  4. 发一个可伸缩线程池大小的python线程池。已通过测试。

    发一个可伸缩线程池大小的线程池. 当任务不多时候,不开那么多线程,当任务多的时候开更多线程.当长时间没任务时候,将线程数量减小到一定数量. java的Threadpoolexcutor可以这样,py的 ...

  5. spring定时任务ThreadPoolTaskScheduler使用注意事项之线程池大小

    背景 最近小伙伴解决了一个工单,描述为"手工推送案件无法推,提示token失效",当前工单状态为待关闭,解决方案为"东软接口不稳定造成的,东软的接口恢复正常后,问题解决& ...

  6. Java-如何合理的设置线程池大小

    想要合理配置线程池线程数的大小,需要分析任务的类型,任务类型不同,线程池大小配置也不同. 配置线程池的大小可根据以下几个维度进行分析来配置合理的线程数: 任务性质可分为:CPU密集型任务,IO密集型任 ...

  7. ThreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别

    工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍ThreadP ...

  8. hreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别

    阅读更多 工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍Th ...

  9. 根据CPU核数合理设置线程池大小

    一般来说池中总线程数是核心池线程数量两倍,只要确保当核心池有线程停止时,核心池外能有线程进入核心池即可. 我们所需要关心的主要是核心池线程的数量该如何设置. 自定义线程池代码 package com. ...

随机推荐

  1. app页面连接到服务器的数据库

    第一步在服务器上写好servlet用于和数据库交互,目前我只写了添加. 第二步app端使用HttpURLConnection连接交互. 效果图: 增加了一条数据:第十一条

  2. (转)null和NULL和nullptr和””区别

    突然想到这个有趣的问题:C语言和C++对大小写是敏感的,也就是说null和NULL是区别对待的.NULL代表空地址,null只是一个符号.便来深究,看了很多资料,总结如下: 其实null和NULL都是 ...

  3. Day3-T1

    原题目 Describe:暴力出奇迹 [ 注意步长0.5!] code: #include<bits/stdc++.h> using namespace std; inline int r ...

  4. ubuntu安装opencv3.2

    把master分支git下来: git clone git@github.com:opencv/opencv.git 查看可用的版本: git tag 选择自己想要的版本号: git reset -- ...

  5. CodeForces - 748B Santa Claus and Keyboard Check

    题意:给定两个字符串a和b,问有多少种不同的字母组合对,使得将这些字母对替换字符串b后,可以变成字符串a.注意字母对彼此各不相同. 分析:vis[u]记录与u可形成关系的字母,若u与v不同,则形成字母 ...

  6. C++ 操作数据库类

    #pragma once #include <string> #include <windows.h> #include <algorithm> #include ...

  7. AT2000 Leftmost Ball 解题报告

    题面 给你n种颜色的球,每个球有k个,把这n*k个球排成一排,把每一种颜色的最左边出现的球涂成白色(初始球不包含白色),求有多少种不同的颜色序列,答案对1e9+7取模 解法 设\(f(i,\;j)\) ...

  8. <强化学习>马尔可夫决策过程MDP

    一.MDP  / NFA    :马尔可夫模型和不确定型有限状态机的不同 状态自动机:https://www.cnblogs.com/AndyEvans/p/10240790.html MDP和NFA ...

  9. JavaScript 之 异步请求

    一. 1.异步(async) 异步,它的孪生兄弟--同步(Synchronous),"同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排 ...

  10. 牛牛的DRB迷宫(DP、二进制编码器)

    牛牛的DRB迷宫I 链接:https://ac.nowcoder.com/acm/contest/3004/A来源:牛客网 题目描述 牛牛有一个n*m的迷宫,对于迷宫中的每个格子都为'R','D',' ...