这篇文章将涉及一个在部署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.更多文章请扫码:
相关推荐
在IT领域,线程池是一种优化资源管理与调度的技术,特别是在多线程环境中,如Web服务器。本实验项目“基于线程池的Web...实际应用中,许多高性能的Web服务器,如Nginx和Apache,都采用了线程池技术来处理高并发请求。
在当前的IT运维领域,随着运维对象数量的激增,如何高效...然而,在构建和应用线程池时,也应当注意一些潜在的陷阱和注意事项,比如合理设定线程池的大小、处理好线程间的同步问题等,以确保线程池能够稳定高效地运行。
对于有界队列,必须仔细考虑队列大小与线程池大小的配合,防止因线程池和队列不匹配造成的性能问题。 综上所述,线程池和阻塞队列是并发编程中的核心概念。它们的合理使用能够显著提升程序性能,降低资源消耗,并...
### Java分布式应用学习笔记07线程池应用 在深入探讨Java分布式应用中线程池的应用之前,我们先来理解一下线程池的基本概念及其在并发编程中的重要性。线程池是Java并发编程的核心技术之一,它通过复用一组预创建的...
6. **线程池的优化**:根据任务特性,可以选择合适的线程池大小。如果任务主要是IO密集型(如网络通信、文件读写),线程池可以设置得稍大些;如果是CPU密集型(如大量计算),则应限制线程数量,以免过多线程间的上...
- **性能优化**:合理配置`server.xml`中的各项参数,如线程池大小、连接器配置等,以提高服务器性能。 - **错误处理**:配置错误页面,以便于更好地处理HTTP状态码对应的错误情况。 - **日志记录**:合理配置日志...
Java Web应用中的线程池调优对于系统的性能和稳定性至关重要。线程池是Java应用程序管理线程的一种机制,它能够有效地控制并发执行的任务数量,从而避免频繁创建和销毁线程带来的开销。线程池的配置直接影响到系统...
- **性能优化**:调整WebSphere的性能参数,如线程池大小、内存分配等,以适应不同的负载需求。 总之,在WebSphere上发布Web应用是一个涉及多个层面的过程,从开发到部署,再到运维,都需要对Java EE、WebSphere...
面这种情况正好适用于这种类型:我们为企业内部网开发解决方案或者在可以严格定义目标平台的系统需求的应用程序中,大小动态可变的线程池适用于不知道可用资源数量的情况,因为在 Web 服务器的情况下,我们不知道...
`ExecutorService`的大小根据系统的CPU核心数动态设定,这样可以更有效地利用硬件资源。 为了添加关闭监听功能,作者创建了另一个监听线程`shutdownThread`,它监听8001端口,当收到特定的关闭命令时,关闭线程池。...
线程池技术可以应用于Web服务系统中,控制服务器系统的最大并发数与最多处理的任务数,有效调节服务器的访问流量,避免服务器有限的资源处于过高的并发设置下。 线程池的大小确定方法: 线程池的大小可以根据实际...
例如,在Web服务器中,可以设置一个固定的线程池大小,以处理HTTP请求;在数据库访问层,可以采用具有动态调整能力的线程池,以应对不同时间段的负载变化。 总之,线程池作为现代软件架构中的重要组成部分,其设计...
APR协议的Connector利用本地库,能够提供更好的性能,特别是在高并发环境下,它更适合运行需要高性能的Web应用。 在server.xml配置文件中,元素的protocol属性可以指定Connector使用的协议。如果没有指定protocol,...
综上所述,这个项目涵盖了Spring Boot应用开发中的多个重要模块,通过学习和实践,开发者可以掌握如何构建一个高效、稳定且功能丰富的Java Web应用。SpringBootSample可能包含了实现这些功能的示例代码,通过研究...
例如,在高并发的Web服务器中,我们可能希望设置较小的`corePoolSize`以减少资源消耗,较大的`maximumPoolSize`来应对瞬间的请求高峰,并使用有限大小的队列避免无限制的缓冲任务。 在实际开发中,我们还需要关注...
1. 适当的线程池大小:根据服务器硬件配置和业务特性,合理设定线程池的大小,避免过度消耗资源或处理请求不及时。 2. 请求队列设计:队列长度应足够大,以缓冲高峰期的请求,但也不能过大导致内存压力。 3. 异常...
通过合理配置线程池的大小,可以根据系统的硬件资源和应用需求达到最佳的性能平衡。同时,线程池也为任务调度提供了更大的灵活性,例如,可以优先处理高优先级的任务,或者限制特定类型任务的数量。 总之,线程池是...
针对实际业务中变化的工作负载,可以考虑使用动态调整线程池大小的策略。例如,根据系统的负载自动调整线程池中的线程数量。这种方式能够更高效地利用系统资源,同时确保系统的稳定性和响应速度。 综上所述,Java...
Java中的线程池Executors java中的线程池Executors是Java...线程池可以应用于各种需要并发执行的场景,例如Web服务器、数据库连接池、消息队列等。使用线程池可以提高系统的性能和可靠性,降低资源消耗和响应时间。
JAVA-WEB应用服务器调优方案 本文档主要介绍了JAVA-WEB应用服务器的调优方案,涵盖了操作系统、JVM、TOMCAT服务器和NGINX反向代理等方面的优化方法。 一、 操作系统参数优化 在选择操作系统时,需要根据项目情况...