Tomcat性能调优
找出对应用表现生成影响的阈值(threshold)在哪里。
初始化内存大小参数
export CATALINA_HOME=/opt/java/tomcat8/ export CATALINA_BASE=/home/deploy/workspace/tomcat/octopus-portal JVM_MAX_MEM=$(free -m|awk '/Mem/{print$2-1300}') JVM_AGG_MAX_MEM=$(echo $JVM_MAX_MEM |awk '{print $0 * 0.7}' | awk -F '.' '{print $1}' ) JVM_AGG_MIN_MEM=$(echo $JVM_MAX_MEM |awk '{print $0 * 0.5}' | awk -F '.' '{print $1}' ) JVM_AGG_NEW_MEM=$(echo $JVM_MAX_MEM |awk '{print $0 * 0.2}' | awk -F '.' '{print $1}' ) ######################################################### #JVM_AGG_MAX_MEM=2048 #JVM_AGG_MIN_MEM=1024 #JVM_AGG_NEW_MEM=512 ########################################################## MY_IP=$(ifconfig eth0 |awk -F '[ |:]+' '/inet /{print $4}') [[ -z $MY_IP ]] && MY_IP=$(ifconfig bond0 |awk -F '[ |:]+' '/inet /{print $4}') MY_PORT=10053 if [[ -z $JVM_MAX_MEM || $JVM_MAX_MEM -lt 1024 ]] ;then JVM_AGG_MAX_MEM=1024 JVM_AGG_MIN_MEM=1024 JVM_AGG_NEW_MEM=512 fi export JAVA_OPTS="-server -XX:+AggressiveOpts -XX:+DoEscapeAnalysis \ -Dcom.sun.management.jmxremote.port=${MY_PORT} \ -Djava.rmi.server.hostname=${MY_IP} \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -Xmx${JVM_AGG_MAX_MEM}m \ -Xms${JVM_AGG_MIN_MEM}m \ -Xmn${JVM_AGG_NEW_MEM}m \ -Xss512K \ -XX:PermSize=128M \ -XX:MaxPermSize=256M \ -XX:SurvivorRatio=8 \ -XX:+UseCompressedOops \ -XX:+UseParNewGC \ -XX:+UseConcMarkSweepGC \ -XX:+CMSClassUnloadingEnabled \ -XX:+UseCMSCompactAtFullCollection \ -XX:CMSFullGCsBeforeCompaction=0 \ -XX:+CMSParallelRemarkEnabled \ -XX:+DisableExplicitGC \ -XX:+UseCMSInitiatingOccupancyOnly \ -XX:CMSInitiatingOccupancyFraction=75 \ -XX:SoftRefLRUPolicyMSPerMB=0 \ "
基准测试
测试工具发起请求的线程数量不应该大于Tomcats配置文件conf/server.xml
里Connector
配置最大线程数maxThread
(默认设置是150)。
常用工具:
- Apache ab:发起请求数量多,适合基准测试。
- Siege:请求速度不如Apache ab,但可以在请求之间生成随机的空闲时间, 还可以从一组指定的URL中随机选择URL。
- Apache Jakarta JMeter:耗资源大、速度不快,但功能强大。
用Apache ab进行基准调校
ab -k -n 100000 -c 149 http://localhost:8080
-
-c
:并发线程数量。 -
-n
:请求总数。 -
-k
:保持联机keep-alive
。
Siege
siege -b -r 671 -c 149 localhost:8080
-
-b
:进行基准测试,即在请求期间不等待。 -
-r
:平均每个线程发起的请求数。 -
-c
:并行的线程数。
这个例子大约发起\(671 \times 149 \approx 100000\)个请求。
Apache Jakarta JMeter
(略)
Tomcat Web Server性能比较
AJP协议是以TCP协议的形式把HTTP协议的请求转给另一个应用, 这样转比直接用HTTP转快。
Tomcat提供的连接器(Connector):
-
JIO(java.io)是由
java.io
包实现的HTTP和AJP协议。 -
NIO(java.nio)由
java.nio
包提供的非阻塞TCP连接实现, 以很少的线程实现大量的连接。 - APR(Apache Portable Runtime)是由Java通过JNI调用libtcnative库。
作为对比,参照一下Apache httpd:
- mod_jk:
- mod_proxy_ajp:httpd用AJP协议把HTTP请求转给Tomcat。
- mod_proxy_http:httpd用HTTP协议把HTTP请求转给Tomcat。
服务器配置
Tomcat 的JVM启动参数:
-Xms384M -Xmx384M -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true
不同连接器的配置:
HTTP JIO连接器:
<Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" redirectPort-"8443" />
HTTP APR连接器:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" enableLookups="false" connectionTimeout="20000" redirectPort-"8443" />
HTTP NIO连接器:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" connectionTimeout="20000" redirectPort-"8443" />
AJP JIO/APR连接器,由设置LD_LIBRARY_PATH
予以切换:
<Connector port="8009" protocol="AJP/1.3" redirectPort-"8443" />
AJP NIO连接器:
<Connector port="0" protocol="AJP/1.3" channelNioSocket.port="8009" channelNioSocket.maxThreads="150" channelNioSocket.maxSpareThreads="50" channelNioSocket.maxSpareThreads="25" channelNioSocket.bufferSize="16384" />
结果分析
(略)
内部调校
停用DNS查询
停用以后,程序中调用getRemoteHost()
时只会取得IP地址,而不是域名。
server.xml
中配置Connector
对象:
<Connector enableLookups="false" />
调整线程数
-
minThreads
:对应访问量低谷,比如低谷时每秒5次访问,每次1秒完成请求。 则最小线程数分配5个就够了。 -
maxThreads
:对应最大并发,设置限制以适应JVM最大内存限制,防止DoS攻击。
这两个数的设置没有现成的规则,尝试不同的值模拟网络流量。
预编译JSP
把JSP当作servlet配置在web.xml
里,启动序编译一遍:
<servlet> <servlet-name>index.jsp</servlet-name> <jsp-file>/index.jsp</jsp-file> <load-on-startup>0</load-on-startup> </servlet>