本文是在Tomcat调优过程中得到的心得(会持续更新),相关环境:
java version "1.8.0_131"
Tomcat 8.5.14
Jmeter 3.1
Jmeter参数:
300线程
1000循环
Tomcat server.xml参数:
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
acceptCount="5000"
maxConnections="20000"
Tomcat JVM参数:-server -Xms4g -Xmx4g
JIT的介入
Tomcat server.xml都保持默认值。
在不重启Tomcat的情况下,两次benchmark得到的throughput数据相差较大:
第一次:9000/s
第二次:17000/s
这也就说明,在Tomcat存在warmup机制,性能表现在warmup之后会更好。
在利用jvisualvm收集了两次benchmark的相关数据,发现这和JDK的compilerThread存在关系,图表如下:
在第一次benchmark的前期,compilerThread动作比较多,此时NIO的吞吐量一直维持在比较低的水平。在第一次benchmark后期,compilerThread降下来了,NIO的吞吐量就上去了。
第二次benchmark几乎没有compilerThread的动作,此时NIO的吞吐量一直维持在比较高的水平。
在经过一番调查之后,发现这是由于JIT对代码做优化,JIT会将频繁执行的代码的bytecode编译成native code,从而加快执行速度。参考文章如下:
Java on Steroids: 5 Super Useful JIT Optimization Techniques
A close look at Java’s JIT: Don’t Waste Your Time on Local Optimizations
maxThreads
根据Tomcat文档的说法,此参数决定了同时最多能够处理多少请求,默认值是200
。而我们的Jmeter脚本是300并发,显然不够,所以调整server.xml
追加Connector
参数:
maxThreads="500"
minSpareThreads="500"
这么配置是提高Tomcat处理线程数,maxThreads
和minSpareThreads
设置为一样是让Tomcat在启动时就创建1000线程,这个和把JVM参数-Xms
、-Xmx
设置为一样是一个道理。
在不重启Tomcat的情况下,两次benchmark得到的throughput数据:
第一次:12000/s
第二次:17000/s
这说明在没有warmup的情况下,maxThreads
的提升能够提升Tomcat的性能表现。
关于maxThreads应该设置多少为合适可以见SO的这个回答:
processorCache
processorCache
控制Tomcat内部RequestProcessor
的缓存池大小,当并发量大于此值时,Tomcat会创建新的RequestProcessor
实例,如果并发量持续大于此值,则会持续创建RequestProcessor
实例。
在这次压力测试过程中,发现如果processorCache=100
时,Tomcat只会保留100个RequestProcessor
,并且会不断创建其实例。见下图:
如果processorCache=400
,则Tomcat会保留300个RequestProcessor
,并且不会创建新的实例,主要是因为Jmeter的线程数为300,也就是说同时最多只会有300个connection,每个connection对应一个RequestProcessor
。
从测试结果上看,processorCache=100
时似乎并不影响测试结果。
gzip压缩
和gzip压缩相关的参数有:compression
、compressibleMimeType
、compressionMinSize
,Tomcat默认是关闭gzip压缩的,gzip压缩能够显著降低带宽。
以下是在warmup之后的benchmark结果,开启gzip能得到17%的性能提升:
compression="on"
:17073.6/scompression="off"
:14548.3/s
但是在benchmark多次之后,发现开启和不开启的结果相近。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。