tomcat默认的参数配置是为开发环境定制的,所以内存和线程的配置都很低,如果直接应用在生产环境,很容易造成性能瓶颈;以下分别从JVM、线程池以及连接参数方面给出优化建议:
1. JVM 优化:
- 当内存为8G时,建议配置:
JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms6144m -Xmx6144m -XX:NewSize=1024m -XX:MaxNewSize=2048m -XX:PermSize=512m -XX:MaxPermSize=512m -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:+DisableExplicitGC"
- 当内存为16G时,建议配置:
JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms13312m -Xmx13312m -XX:NewSize=3072m -XX:MaxNewSize=4096m -XX:PermSize=512m -XX:MaxPermSize=512m -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:+DisableExplicitGC"
- 当内存为32G时,建议配置:
JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms29696m -Xmx29696m -XX:NewSize=6144m -XX:MaxNewSize=9216m -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:+DisableExplicitGC"
参数解释:
- -Dfile.encoding:默认文件编码
- -server:表示这是应用于服务器的配置,JVM内部会有特殊处理(GC策略,内存分配策略、以及并发处理能力等)
- -Xmx1024m:设置JVM最大可用内存为1024MB
- -Xms1024m:设置JVM最小内存为1024MB.此值可用设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
- -XX:NewSize:设置年轻代大小
- -XX:MaxNewSize:设置最大年轻代大小
- -XX:PermSize:设置永久代大小,默认是物理内存的1/64
- -XX:MaxPermSize:设置最大永久代大小,默认物理内存的1/4(如果有大文件导出时,一定要设置该值和-XX:PermSize)
- -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与终身代的比值(除去永久代)。设置为4,则年轻代与终身代所占比值为1:4,年轻代占整个堆栈的1/5
- -XX:MaxTenuringThreshold=10:设置垃圾最大年龄,默认为:15。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代被回收的概率。
- -XX:+DisableExplicitGC:这个将会忽略手动调用GC的代码,使得System.gc()的调用无效,完全不会触发任何GC
2. 线程池配置
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="100" prestarminSpareThreads="true" maxQueueSize="100" />
参数解释:
- maxThreads:最大并发数,默认值200,一般建议在500~800,根据硬件设施和业务来判断。
- minSpareThreads:Tomcat初始化时创建的线程数,默认为25
- prestarminSpareThreads:在Tomcat初始化的时候就初始化minSpareThreads的参数值,如果不等于true,minSpareThreads的值就没啥效果了
- maxQueueSize:最大的等待队列数,超过则拒绝请求
3. 修改连接参数
<Connector exexutor="tomcatThreadPool" port="8080" protocol="prg.apache.coyote.http11.http11Nio2Protocol"connectionTimeout="20000" maxConnections="10000" redirectPort="8443" enableLookups="false" acceptCount="100" maxPostSize="10485760" compression="on" disableUploadTimeout="true" compressionMinSize="2048" acceptorThreadCount="2" compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript" YRIEncoding="utf-8" />
参数解释:
- protocol:Tomcat6、7设置为nio更好:org.apache.coyote.http11.http11NioProtocol,Tomcat8的nio为:org.apache.coyote.http11.http11Nio2Protocol
- enableLookups:禁用DNS查询
- acceptCount:指定当所有可用处理请求的线程数都被使用时,可以放入处理队列中的请求数,超过这个数的请求将不被吹,默认设置100
- maxPostSize:以FORM URL参数方式的POST提交方式,限制提交最大的大小,默认为2097152(2M),它使用的单位是字节。如果要禁用限制,则可用设置为-1.
- acceptorThreadCount:接受连接的线程数量,默认为1.一般这个值需要改动的时候是因为该服务器是一个多核CPU,如果是多核CPU一般配置为2.
4. 生产配置测试比较
4.1 生产配置
- 机器配置:虚机 4C4G
- 内存配置:JAVA_OPTS="-Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8 -server -Xms3072m -Xmx3072m -XX:PermSize=512m -XX:MaxNewSize=512m -XX:MaxPermSize=512m"
- 连接参数:
<Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" compression="on" compressionMinSize1="2048" disableUploadTimeout="true" maxThreads="1024" minSpareThreads="64" maxSpareThreads="128" maxHttpHeaderSize="8192" enableLookups="false" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,,application/octet-stream" />
4.2 测试结果
并发条件 |
吞吐量 |
每秒请求数 |
每秒请求数(acceptorThreadCount="4") |
10 |
1572 |
594.37 |
762.06 |
20 |
1455 |
768.61 |
1382.87 |
30 |
4761 |
785.67 |
1310.27 |
40 |
5000 |
1510.19 |
1724.18 |
50 |
5807 |
1639.50 |
2025.41 |
100 |
6962.8 |
1680.91 |
1999.36 |
200 |
6054 |
1061.28 |
1857.65 |
300 |
6827 |
979.14 |
1553.41 |
400 |
4198 |
1055.51 |
1879.25 |
500 |
6460 |
734.67 |
1975.80 |
1000 |
4886 |
734.91 |
902.59 |
从测试结果分析连接参数增加:acceptorThreadCount="4"(接受连接的线程数量,默认为1.一般这个值需要改动的时候是因为该服务器是一个多核CPU,如果是多核CPU一般配置为2.) 能够增加服务器每秒处理的请求数量;建议生产环境加上该参数。