如何确定Tomcat中的最佳线程数?

Ste*_*idt 23 multithreading tomcat6

如何在Tomcat中确定maxSpare,minSpare和maxThreads,acceptCount等的最佳数量?是否存在最佳实践?

我确实理解这需要基于硬件(例如每个核心),并且只能作为特定硬件上进一步性能测试和优化的基础.

Sim*_*nni 52

"多少线程问题"是一个相当大而复杂的问题,并且无法用简单的经验法则来回答.

考虑到您拥有多少个核心对于多线程应用程序非常有用,这些应用程序往往会占用大量CPU,例如数字运算等.对于网络应用程序来说,这种情况很少发生,网络应用程序通常不是由CPU而是由其他因素造成的.

一个常见的限制是您和其他外部系统之间的延迟,尤其是您的数据库.每次请求到达时,它可能会多次查询数据库,这意味着通过JDBC连接传输一些字节,然后等待这些字节到达数据库(即使是在localhost上仍存在小的延迟) ,然后等待DB考虑我们的请求,然后等待数据库处理它(数据库本身将等待磁盘寻找某个区域)等...

在这段时间内,线程处于空闲状态,因此另一个线程可以轻松地使用该CPU资源来执行有用的操作.在等待数据库响应时花费40%到80%的时间是很常见的.

在连接的另一端也发生同样的情况.当你的一个线程正在将其输出写入浏览器时,CLIENT连接的速度可能会使你的线程空闲,等待浏览器确认已收到某个数据包.(几年前这是一个相当严重的问题,最近的内核和JVM使用更大的缓冲区来防止你的线程以这种方式空闲,但是在你的web应用服务器面前的反向代理,甚至只是一个httpd,对于避免人们来说真的很有用与互联网连接不良充当DDOS攻击:))

考虑到这些因素,线程数通常应该比您拥有的核心数多得多.即使在简单的双核或四核服务器上,您也应该至少配置几十个线程.

那么,什么限制了你可以配置的线程数量?

首先,每个线程(用于)消耗大量资源.每个线程都有一个堆栈,占用RAM.而且,每个Thread实际上会在堆上分配东西来完成它的工作,再次消耗RAM,并且线程之间的切换(上下文切换)对于JVM/OS内核来说非常繁重.

这使得很难"平稳地"运行具有数千个线程的服务器.

鉴于这张图片,有许多技术(主要是:尝试,失败,调整,再试一次)来确定应用程序需要多少线程:

1)尝试了解线程花费时间的位置.有许多好的工具,但即使是jvisualvm分析器也可以是一个很好的工具,或者是一个产生汇总时序统计数据的跟踪方面.他们花在等待外部事物上的时间越多,你就越能在空闲时间产生更多的线程来使用CPU.

2)确定您的RAM使用情况.鉴于JVM将使用一定数量的内存(最明显的是permgen空间,通常高达100兆字节,jvisualvm将告诉你),无论你使用多少线程,尝试使用一个线程然后使用10然后使用一百,同时用jmeter或其他任何东西强调应用程序,并看看堆使用量将如何增长.这可能构成一个硬性限制.

3)尝试确定目标.每个用户请求都需要处理一个线程.如果你的平均响应时间是每个"获取"200毫秒(最好不考虑加载图像,CSS和其他静态资源),那么每个线程能够每秒服务4/5页.如果每个用户都希望每3/4秒"点击"一次(取决于,它是一个浏览器游戏还是一个有很多长文本的网站?),那么一个线程将"服务20个并发用户",无论它意味着什么.如果在高峰时段有500个单用户在1分钟内访问您的站点,那么您需要足够的线程来处理它.

4)碰撞测试上限.使用jmeter,在备用虚拟机上配置具有大量线程的服务器,并查看当超过某个限制时响应时间将变得更糟.不仅仅是硬件,底层操作系统的线程实现在这里很重要,但无论它在什么方面都会占用CPU花费更多时间来确定运行哪个线程而不是实际运行它,而且这个数字并不是那么令人难以置信高.

5)考虑线程将如何影响其他组件.每个线程可能会使用一个(或可能多个)连接到数据库,数据库是否能够处理50/100/500并发连接?即使您使用的是分片的nosql服务器集群,服务器场是否在这些计算机之间提供足够的带宽?还有什么能与web-app服务器在同一台机器上运行?阿纳奇httpd?乌贼?数据库本身?数据库的本地缓存代理,如mongos或memcached?

我已经看到生产中只有4个线程+ 4个备用线程的系统,导致该服务器完成的工作仅仅是调整图像大小,因此它几乎占用了100%的CPU,而其他硬件或多或少配置了相同的硬件.几百个线程,因为webapp正在对外部系统进行大量的SOAP调用,并且花费大部分时间等待答案.

Oce你已经确定了约.最适合您的webapp的最小和最大线程,然后我通常以这种方式配置它:

1)基于RAM,其他外部资源和上下文切换实验的约束,绝对最大值不得达到.因此,使用maxThreads将其限制为该数字的一半或3/4.

2)如果应用程序相当快(例如,它暴露通常发送响应的REST Web服务是几毫秒),那么您可以配置一个大的acceptCount,最多相同数量的maxThreads.如果您的Web应用程序服务器前面有负载均衡器,请设置一个小的acceptCount,最好让负载均衡器查看未接受的请求并切换到另一台服务器,而不是将用户置于已经忙碌的服务器上.

3)由于启动一个线程(仍然)被认为是一个繁重的操作,使用minSpareThreads在高峰时间到达时准​​备好一些线程.这又取决于您期望的负载类型.使用minSpareThreads,maxSpareThreads和maxThreads设置是合理的,这样一定数量的线程总是准备好,永远不会回收,并且性能是可预测的.如果您在专用计算机上运行tomcat,则可以提升minSpareThreads和maxSpareThreads而不会有任何阻碍其他进程的危险,否则将其调低,因为线程是与大多数操作系统上运行的其余进程共享的资源.