在部署 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. tx2系统备份与恢复

    https://blog.csdn.net/ycy_dy/article/details/80493392 https://blog.csdn.net/piaopiaopiaopiaopiao/art ...

  2. PHP的操作符与控制结构

    一.操作符  操作符是用来对数组和变量进行某种操作运算的符号. 算术操作符 操作符 名称 示例 + 加 $a+$b - 减 $a-$b * 乘 $a*$b / 除 $a/$b % 取余 $a%$b 复 ...

  3. CSS font-family 各字体一览表

    windows常见内置中文字体字体中文名 字体英文名宋体                      SimSun(浏览器默认) 黑体                      SimHei 微软雅黑 ...

  4. URAL_1018 Binary Apple Tree 树形DP+背包

    这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过 ...

  5. localStorage中使用json

    function setLocalJson(name, json) { json = JSON.stringify(json); localStorage.setItem(name, json)} f ...

  6. [转]Linux命令行上传文件到 百度网盘 bypy

    安装软件工具: apt-get install python-pip pip install requests pip install bypy 授权登陆: 执行 bypy info,显示下边信息,根 ...

  7. 身边的人工智能&人工智能发展史

    智能家具 扫地机器人 智能音箱 个人助手 在线翻译 谷歌翻译 微软翻译 YouTube 视频翻译 图像识别 人脸识别 AI+摄像头 下棋高手 Alphago 2017年打败柯洁 成为世界第一 Alph ...

  8. Mac 用终端(命令行)打开vscode编辑器

    1.打开控制面板(⇧⌘P) 2.输入 shell command 在提示里看到 Shell Command: Install ‘code’ command in PATH, 就可以了. 3.使用: c ...

  9. python爬取招聘网站数据

    # -*- coding: utf-8 -*- # 爬虫分析 from bs4 import BeautifulSoup from lxml import etree from selenium im ...

  10. windows更新系统系统时无法更新

    win7系统显示“windows update当前无法检查更新,因为未运行服务,您可能需要重新启动计算机” 解决方法 1.win+r打开运行窗口,输入CMD 2.在dos窗口中输入命令“net sto ...