`
冰糖葫芦
  • 浏览: 293796 次
社区版块
存档分类
最新评论

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

阅读更多

 这篇文章将涉及一个在部署Web应用产品和Web系统性能测试中都会出现的问题:如何决定Web应用的线程池大小?

线程池(Thread Pool)

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

请注意,并发和并行是不同的。并发请求是指在任何一个时间点,所有被处理的请求中只有只有很少一部分占用CPU(译者注:轮流使用CPU)。并行是指在任何一个时间点,所有被处理的请求同时在CPU上运行。

在非阻塞式(NO-Blocking)应用中(如NodeJs),一个单独的线程或进程可以并发处理多个请求。而在多核CPU中则可以通过增加线程或进程数来实现并行处理。

在阻塞式IO应用中(如java的SringMVC,一个线程只能同时处理一个并发请求。如果想要并发处理多个请求只能通过增加线程数来实现。

CPU消耗型应用

对于CPU消耗型应用来说,线程池的大小应该和单台服务器的CPU个数相同。对于这类应用由于线程上下文切换增加线程数反而会妨碍对请求的处理,同时还会增加响应时间。

非阻塞式IO应用由于在请求被处理时并不需要等待请求处理完成,因此属于CPU消耗型的应用。

IO消耗型应用

由于IO消耗型应用依赖于下行流量所在系统的响应时间,而且一个线程在其他系统响应完成之前将一直阻塞,所以决定IO消耗型应用的线程池大小变得更加困难。对于这类型应用,我们就像在阻塞式IO应用文章中讲的,通过增加线程数来提高CPU利用率。

科特尔法则(Little’s Law)

科特尔法则通常被用在非技术领域,例如告诉银行柜台出纳员还有多少客户在等待请求处理。

 

下面是维基百科对科特尔法的说明,英文原文如下:

The average number of threads in a system (Threads) is equal average web request arrival rate (WebRequests per sec), multiplied by the average response time (ResponseTime)

译文:一个系统的平均线程数(线程数)等于平均请求的到达率(每秒请求数)乘以平均响应时间(响应时间)

公式:线程数=每秒请求数 X 响应时间

公式说明:

线程数系统所能处理的线程数量

每秒请求数每秒钟所能处理的请求数

响应时间处理一个请求所花费的时间

当然,上边的公式给出了处理多少请求需要多少线程,但是并没有考虑线程对CPU的占用率等情况,也没有说明对于多核的单台机器应该分配多少线程。

通过测试决定线程池大小

要分配合适大小的线程池就需要在吞吐量和响应时间这两个要素之间寻求平衡点。从每个CPU最少线程数开始(即线程数=cpu数),系统线程数和平均响应时间成正比直到CPU使用率达到最大或者响应时间不再减少为止。

下图说明了请求数、CPU和响应时间之间的关系。

CPU和请求数的图中展示了随着Web系统负载量不断增加时CPU的使用情况。

响应时间和请求数的图中展示了Web系统负载量的增加对响应时间的影响。

绿色的点表示吞吐量和响应时间的最优点。

线程池大小=CPU核心数

上图展示的是阻塞式IO消耗型应用在线程池大小等于CPU核心数量时的情况。线程由于要等待下行流量的IO处理所以会阻塞,而由于线程的阻塞使响应时间进一步增加,而且即使CPU的占用率非常低,但是线程池中所有线程都处于阻塞状态,那么应用还是会拒绝请求。

大的线程池

上图展示的是阻塞式IO消耗型应用在大的线程池下的使用情况。由于线城池数量大,线程上下文切换也变得非常频繁,而正是这些没必要的上下文切换使得应用还没有达到最大吞吐量时CPU就已经达到最大占用率了。请求响应时间也由于频繁的上下文切换而快速增长。

最优线程池大小

上图展示的是阻塞式IO消耗型应用在最优线程池下的情况。在高吞吐量和更少线程上文切换的情况下CPU得到了高效的利用。同时我们注意到,好的响应时间取决于在线程更少被阻断(上下文切换)的情况下对请求的高效处理。

线程池隔离

在大多数应用中,只有少数类型的请求会比其他请求更耗时,但这少数的耗时请求会影响整个系统的性能。有两个办法可以解决这个问题:

1)将比较耗时的请求隔离开来专门处理

2)在同一个应用中为耗时的web请求单独分配一个线程池

决定一个阻塞式IO消耗型应用的最优线程池大小是一件困难的事情,这通常需要通过多个性能测试来决定。如果在一个应用中使用多个线程池,会使对线程池的优化进一步复杂化。

 

 

 

1. 本文由程序员学架构翻译,mathew同学校审

2. 本文译自How To Determine Web Application Thread Pool Size - Venkatesh CM

3. 转载请务必注明本文出自:程序员学架构(微信号:archleaner )

4.更多文章请扫码:

  • 大小: 38.7 KB
2
0
分享到:
评论

相关推荐

    WebSphere参数调优.txt

    同时,在这里也可以设置线程池自增长功能,点选“可增长线程池”选项,使得即使设置了最大的线程池大小,当并发的EJB请求过多,线程池的大小还是可以超过预先设置的最大值。 3、应用程序服务器 > server1 >ORB 服务...

    2020美团技术年货-合集(前端+后台+数据+算法+运维).pdf

    前端 1 移动端UI一致性解决方案 1 ...Native地图与Web融合技术的应用与实践 230 后台 245 Java线程池实现原理及其在美团业务中的实践 245 美团万亿级 KV 存储架构与实践 276 Java中9种常见的CMS GC问题分析

    java微信公众号MVC开发框架

    @Weixin需要配置value值,这个实际就是微信服务器配置里面URL最后的部分,当然不包含域名和web应用的上下文,切记,不能包含web应用上下文,其他4个部分配置内容也是公众号配置内容,我们只需要登录到公众号看下填...

    Java优化编程(第2版)

    第14章 ajax技术与web应用性能优化 14.1 了解ajax 14.2 通过ajax技术改善web应用性能 14.2.1 ajax技术实现 14.2.2 ajax技术性能优化实例 小结 第15章 其他优化话题 15.1 用weakhashmap屏蔽内存泄漏 15.2 优化java...

    tastefulserver:用C ++编写的多线程Web服务器(使用Qt)

    雅致的服务器Tasteful Server为高性能网络应用程序提供了多线程服务器体系结构。 它是用C ++编写的,并使用Qt库。 您可以使用自己的处理程序来指定许多服务器。 这些服务器共享一个用户定义大小的线程池,以处理传入...

    Android应用调度工具Init.zip

    // 设置线程池大小 Init.setThreadPoolSize(...) // 取消一个已经开始的flow Init.cancel(...) // 获得flow状态 Init.getFlowStatus(...) // 获得特定的task状态 flow.getTaskStatus(taskName) // 设置超时限制...

    vc++ 应用源码包_1

    然后获取文件头,得到文件大小,然后再下载。重点函数是ThreadDownLoad。下载完之后用FileCombine合并文件。Mydownload.cpp底端的fnMyDownload函数是下载器的关键函数。 点对点多线程断点续传软件《传圣》源代码 ...

    awesome-software-engineering:精选软件工程资源精选清单

    很棒的软件工程 精选的软件工程资源精选清单。...Web Service Basic ,Web系统上的线程池 JVM堆大小选项,尤其是Xmx,Xms GC概念和调整(G1GC) JVM -XX参数 jmap histo,转储 完整堆转储分析,检测内存泄漏等 Py

    vc++ 应用源码包_2

    然后获取文件头,得到文件大小,然后再下载。重点函数是ThreadDownLoad。下载完之后用FileCombine合并文件。Mydownload.cpp底端的fnMyDownload函数是下载器的关键函数。 点对点多线程断点续传软件《传圣》源代码 ...

    vc++ 应用源码包_6

    然后获取文件头,得到文件大小,然后再下载。重点函数是ThreadDownLoad。下载完之后用FileCombine合并文件。Mydownload.cpp底端的fnMyDownload函数是下载器的关键函数。 点对点多线程断点续传软件《传圣》源代码 ...

    vc++ 应用源码包_5

    然后获取文件头,得到文件大小,然后再下载。重点函数是ThreadDownLoad。下载完之后用FileCombine合并文件。Mydownload.cpp底端的fnMyDownload函数是下载器的关键函数。 点对点多线程断点续传软件《传圣》源代码 ...

    vc++ 应用源码包_3

    然后获取文件头,得到文件大小,然后再下载。重点函数是ThreadDownLoad。下载完之后用FileCombine合并文件。Mydownload.cpp底端的fnMyDownload函数是下载器的关键函数。 点对点多线程断点续传软件《传圣》源代码 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part1

    22.6.3 Microsoft ASP.NET Web窗体和XML Web服务应用程序 22.6.4 Microsoft SQL Server 22.6.5 更多的用法只局限于你自己的想象力 22.7 高级宿主控制 22.7.1 使用托管代码管理CLR 22.7.2 编写健壮的宿主应用...

    CLR.via.C#.(中文第3版)(自制详细书签)

    22.6.3 Microsoft ASP.NET Web窗体和XML Web服务应用程序 22.6.4 Microsoft SQL Server 22.6.5 更多的用法只局限于你自己的想象力 22.7 高级宿主控制 22.7.1 使用托管代码管理CLR 22.7.2 编写健壮的宿主应用...

    CLR.via.C#.(中文第3版)(自制详细书签)Part3

    22.6.3 Microsoft ASP.NET Web窗体和XML Web服务应用程序 22.6.4 Microsoft SQL Server 22.6.5 更多的用法只局限于你自己的想象力 22.7 高级宿主控制 22.7.1 使用托管代码管理CLR 22.7.2 编写健壮的宿主应用...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    22.6.3 Microsoft ASP.NET Web窗体和XML Web服务应用程序 22.6.4 Microsoft SQL Server 22.6.5 更多的用法只局限于你自己的想象力 22.7 高级宿主控制 22.7.1 使用托管代码管理CLR 22.7.2 编写健壮的宿主应用...

Global site tag (gtag.js) - Google Analytics