目录
2.4.2 调整连接器connector的并发处理能力.. 6
1 JDK优化
使用mixedmode版本的JDK,稳定版本,1.7或1.8
2 Tomcat优化
2.1 版本选择
2.1.1 Apache Tomcat 7.x
是目前的开发焦点。它在汲取了Tomcat 6.0.x优点的基础上,实现了对于Servlet 3.0、JSP2.2和EL 2.2等特性的支持。除此以外的改进列表如下:
1.1 Web应用内存溢出侦测和预防
1.2 增强了管理程序和服务器管理程序的安全性
1.3 一般 CSRF保护
1.4 支持web应用中的外部内容的直接引用
1.5 重构 (connectors, lifecycle)及很多核心代码的全面梳理
2.1.2 Apache Tomcat 6.x
在汲取Tomcat 5.5.x优点的基础上,实现了Servlet2.5和JSP 2.1等特性的支持。除此以外的改进列表如下:
2.1 内存使用优化
2.2 更大的IO容量
2.3 重构聚类
2.2 内存优化
当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。
2.2.1 设置原则
① 先折算本机上其他服务进程需要的内存,然后修改堆大小。一般设置为(70-Xms=-Xmx=服务器内存*70%%),有多台tomcat则均分或根据业务情况分配(需要有监控数据支持);
② 建议设置“初始化内存大小”=“可以使用的最大内存”,这样可以减少平凡分配堆而降低性能。
③ 对象生成速率决定了-Xmn和-Xmx之比,如果是长连接且对象生成速率很快,则比例要大些好(如1:3),否则经常引发young gc;参考采用1:9,把新生代内存设置得太大会导致young gc时间较长;
④xmn的值应该是保证够用(够http并发请求之用)的前提下设置得尽量小;
2.2.2 设置方法
修改文件$CATALINA_HOME/bin/catalina.sh,在文件首部增加如下设置(根据实际情况调整数值):
JAVA_OPTS="-server -Xms2048m -Xmx2048m -Xss512k"
非tomcat类可以使用:
$ nohup java -jar XXX.jar -Xms2048m -Xmx2048m -Xss512k
参数说明:
-server //服务器模式,一定要作为第一个参数,在多个CPU时性能佳
-Xmx2g//JVM最大允许分配的堆内存,按需分配
-Xms2g//JVM初始分配的堆内存,cpu性能高时此值应设的大一些。一般和Xmx配置成一样以避免每次gc后JVM重新分配内存。
-Xmn256m//young generation的内存大小,一般设置为Xmx的3、4分之一,整个JVM内存=年轻代 + 年老代 + 持久代。
-XX:PermSize=128m//持久代内存大小
-Xss256k//设置每个线程的栈stack大小
-XX:+UseParNewGC//缩短minor收集的时间
-XX:+UseConcMarkSweepGC//缩短major收集的时间(此选项在Heap Size 比较大而且Major收集时间较长的情况下使用更合适)
-XX:+DisableExplicitGC//忽略手动调用GC,System.gc()的调用就会变成一个空调用,完全不触发GC
-XX:+UseConcMarkSweepGC//使用并发标记清除(CMS)收集器
-XX:+CMSParallelRemarkEnabled//降低标记停顿
-XX:+UseCMSCompactAtFullCollection//在FULL GC的时候对年老代的压缩
-XX:LargePageSizeInBytes=128m//内存页的大小
-XX:+UseFastAccessorMethods//原始类型的快速优化
-XX:+UseCMSInitiatingOccupancyOnly//使用手动定义初始化定义开始CMS收集
-XX:CMSInitiatingOccupancyFraction=70//使用cms作为垃圾回收使用70%后开始CMS收集
示例:
JAVA_OPTS="-server-showversion -Xms12g -Xmx12g -XX:PermSize=256m -XX:MaxPermSize=256m"
JAVA_OPTS="$JAVA_OPTS-d64 -XX:CICompilerCount=8 -XX:+UseCompressedOops"
JAVA_OPTS="$JAVA_OPTS-XX:SurvivorRatio=4 -XX:TargetSurvivorRatio=90"
JAVA_OPTS="$JAVA_OPTS-XX:ReservedCodeCacheSize=256m -XX:-UseAdaptiveSizePolicy"
JAVA_OPTS="$JAVA_OPTS-Duser.timezone=Asia/Shanghai -XX:-DontCompileHugeMethods"
JAVA_OPTS="$JAVA_OPTS-Xss256k -XX:+AggressiveOpts -XX:+UseBiasedLocking"
JAVA_OPTS="$JAVA_OPTS-XX:MaxTenuringThreshold=31 -XX:+CMSParallelRemarkEnabled "
JAVA_OPTS="$JAVA_OPTS-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=256m-XX:+UseFastAccessorMethods"
JAVA_OPTS="$JAVA_OPTS-XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true"
JAVA_OPTS="$JAVA_OPTS-XX:+UseGCOverheadLimit -XX:AllocatePrefetchDistance=256-XX:AllocatePrefetchStyle=1"
JAVA_OPTS="$JAVA_OPTS-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxGCPauseMillis=200"
根据进程号查看进程的内存使用情况:
$/home/dev/jdk1.7.0_25/bin/jmap -heap 30806
Attachingto process ID 30806, please wait...
Debuggerattached successfully.
Servercompiler detected.
JVMversion is 23.25-b01
usingthread-local object allocation.
ParallelGC with 4 thread(s)
HeapConfiguration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1398800384 (1334.0MB)
NewSize = 838860800 (800.0MB)
MaxNewSize = 838860800 (800.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 85983232 (82.0MB)
G1HeapRegionSize = 0 (0.0MB)
HeapUsage:
PSYoung Generation
EdenSpace:
capacity = 629145600 (600.0MB)
used = 592968424 (565.4987564086914MB)
free = 36177176 (34.501243591308594MB)
94.2497927347819% used
FromSpace:
capacity = 104857600 (100.0MB)
used = 0 (0.0MB)
free = 104857600 (100.0MB)
0.0% used
ToSpace:
capacity = 104857600 (100.0MB)
used = 0 (0.0MB)
free = 104857600 (100.0MB)
0.0% used
PSOld Generation
capacity = 234881024 (224.0MB)
used = 0 (0.0MB)
free = 234881024 (224.0MB)
0.0% used
PSPerm Generation
capacity = 24510464 (23.375MB)
used = 24318800 (23.192214965820312MB)
free = 191664 (0.1827850341796875MB)
99.21803193933823% used
可查看30806号进程的MaxHeapSize 等参数是否已经生效。
2.3 禁用DNS查询
当web应用程序向要记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名转换为IP地址。DNS查询需要占用网络,并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。为了消除DNS查询对性能的影响我们可以关闭DNS查询。
设置方法:
修改server.xml文件中的enableLookups参数值:
<Connectorport="80" maxThreads="150" minSpareThreads="25"maxSpareThreads="75" enableLookups="false"redirectPort="8443" acceptCount="100" debug="0"connectionTimeout="20000" disableUploadTimeout="true"/>
2.4 并发优化
通过应用程序的连接器(Connector)进行性能控制的的参数是创建的处理请求的线程数。Tomcat使用线程池加速响应速度来处理请求。在Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。
2.4.1 调整线程数
minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为 10
maxProcessors:最大连接线程数,即:并发处理的最大请求数(防止流量不可控制或者恶意的服务攻击,从而导致超出了虚拟机使用内存的大小),默认值为 75
acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。应大于等于 maxProcessors ,默认值为 100
connectionTimeout:网络连接超时,单位:毫秒。设置为 0 表示永不超时,这样设置有隐患的。通常可设置为30000 毫秒
KeepAlive on:打开KeepAlive支持
keepAliveTimeout:长连接最大保持时间(单位为秒)。
maxKeepAliveRequests : 最大长连接个数(1表示禁用,-1表示不限制个数,默认100个。一般设置在100~200之间)
maxHttpHeaderSize:http 请求头信息的最大程度,超过此长度的部分不予处理。一般8K
bufferSize:connector为进入流量创建的流缓冲区的大小(单位为字节)。缺省情况下,bufferSize=2048。
2.4.2 调整连接器connector的并发处理能力
属性说明:
maxThreads: 当Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。
minSpareThreads:Tomcat初始化时应当创建的 socket 线程数
maxSpareThreads:Tomcat连接器的最大空闲 socket 线程数,一旦空闲的线程数超过这个值,Tomcat就会关闭多余的空闲socket线程。
redirectPort: 在需要基于安全通道的场合,把客户请求转发到基于SSL 的redirectPort 端口
URIEncoding: URL统一编码
配置示例:
<Connector port="9027"
protocol="HTTP/1.1"
maxHttpHeaderSize="8192"
maxThreads="1000"
minSpareThreads="100"
maxSpareThreads="1000"
minProcessors="100"
maxProcessors="1000"
enableLookups="false"
URIEncoding="utf-8"
acceptCount="1000"
redirectPort="8443"
disableUploadTimeout="true"/>
最好的方式是多设置几次并且进行测试,观察响应时间和内存使用情况。在不同的机器、操作系统或虚拟机组合的情况下可能会不同,而且并不是所有人的web站点的流量都是一样的,因此没有一刀切的方案来确定线程数的值。
2.5 压缩
HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求服务器对应资源后,从服务器端将资源文件压缩,再输出到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML ,CSS,Javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP ,Servlet,SHTML等输出的网页也能进行压缩,压缩效率也很高。
Tomcat5.0以后的版本是支持对输出内容进行压缩的,使用的是gzip压缩格式。
配置方法:
修改%TOMCAT_HOME%/conf/server.xml如下:
<Connectorport="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"executor="tomcatThreadPool" URIEncoding="utf-8"
compression="on"
compressionMinSize="50" noCompressionUserAgents="gozilla,traviata"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"/>
说明:
• compression="on" 打开压缩功能
• compressionMinSize="50" 启用压缩的输出内容大小,默认为2KB
• noCompressionUserAgents="gozilla,traviata" 对于以下的浏览器,不启用压缩
• compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" 哪些资源类型需要压缩
2.6 简化应用
webapps与server/wenapps下的应用,减少启动的应用,提高安全性。
配置方法:
删除webapps下所有文件
# rm –fr $CATALINA_HOME/webapps/*
删除server/webapps下所有文件
# rm –fr $CATALINA_HOME/server/webapps/*
2.7 参考示例
一个web服务器配置参考实例。
旧有配置:
<Connectorport="9027"
protocol="HTTP/1.1"
maxHttpHeaderSize="8192"
maxThreads="1000"
minSpareThreads="25"
maxSpareThreads="75"
enableLookups="false"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
connectionTimeout="20000"
URIEncoding="utf-8"
acceptCount="200"
redirectPort="8443"
disableUploadTimeout="true" />
后来在访问量达到3 百万多的时候出现性能瓶颈。更改后的配置:
<Connectorport="9027"
protocol="HTTP/1.1"
maxHttpHeaderSize="8192"
maxThreads="1000"
minSpareThreads="100"
maxSpareThreads="1000"
minProcessors="100"
maxProcessors="1000"
enableLookups="false"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
connectionTimeout="20000"
URIEncoding="utf-8"
acceptCount="1000"
redirectPort="8443"
disableUploadTimeout="true"/>
3 APR库的使用
概述:
APR(Apache Portable Runtime)让tomcat具备如下特性:
① 使用高级IO功能,如sendfile、epoll和OpenSSL,
② 使用OS 级别的功能,如随机数生成、系统状态等;
③ 本地进程处理方面的功能,如内存共享、NT pipes和Unix sockets。
APR可以大大提升Tomcat对静态文件的处理性能,同时如果你使用了HTTPS方式传输的话,也可以提升SSL的处理性能。
tomcat默认采用的BIO模型,在几百并发下性能会有很严重的下降。tomcat自带还有NIO的模型,另外也可以调用APR的库来实现操作系统级别控制。
NIO模型是内置的,调用很方便,只需要将server.xml配置文件中protocol修改成org.apache.coyote.http11.Http11NioProtocol,重启即可生效。
APR则需要安装第三方库,在高并发下会让性能有明显提升。
具体安装办法可以参考http://www.cnblogs.com/huangjingzhou/articles/2097241.html。安装完成后重启即可生效。
官方对三种方式的区别的比较:
Java Blocking Connector/BIO | a Nio Blocking Connector/NIO | native Connector/APR | |
Classname | AjpProtocol | AjpNioProtocol | AjpAprProtocol |
Tomcat Version | 3.x onwards | 7.x onwards | 5.5.x onwards |
Support Polling | NO | YES | YES |
Polling Size | N/A | maxConnections | maxConnections |
Read Request Headers | Blocking | Sim Blocking | Blocking |
Read Request Body | Blocking | Sim Blocking | Blocking |
Write Response | Blocking | Sim Blocking | Blocking |
Wait for next Request | Blocking | Non Blocking | Non Blocking |
Max Connections | maxConnections | maxConnections | maxConnections |
其他人员对Bio、Nio、Apr模式的测试结果:
对于这几种模式,ab命令模拟1000并发测试10000词,每种方式反复测试了10多次,并且在两个服务器上都测试了一遍。结果发现Bio和Nio性能差别非常微弱。但是采用apr,连接建立的速度会有50%~100%的提升。直接调用操作系统层确实增加处理速度,强烈推荐apr方式!
修改成支持NIO的类型的步骤:
(1)server.xml中的配置如下 :
<Connectorport="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443"/>
(2)进行测试,被打开nio配置,启动时的信息,如下:
[dev@kfapp1logs]$ grep -A 10 "NioSelectorPool getSharedSelector"catalina.out
Aug22, 2016 8:27:34 PM org.apache.tomcat.util.net.NioSelectorPoolgetSharedSelector
INFO:Using a shared selector for servlet write/read
Aug22, 2016 8:27:34 PM org.apache.coyote.AbstractProtocol init
INFO:Initializing ProtocolHandler ["ajp-bio-8019"]