一、概述
Tomcat作为很多中小企业的Web应用服务器,因其轻量级,开源,易用,应用广泛等特性,我们实际工作中经常接触到,但有时基于此的我们的web网站可能会出现各种各样的性能问题,那我们如何对Tomcat性能调优呢?本文将从调优方面切入概述下一些日常方法(如承受更高的并发量 ),同时回顾了一下Tomcat的工作原理,及与其他web应用解决方案的对比。
Tomcat有三种运行模式 ,分别是PIO、NIO、APR,在Linux下在Tomcat7及以下默认采用APR模式 。
PIO为阻塞式IO:一个线程处理一个请求,在高并发情况时,多线程访问下会导致资源紧张。
NIO为Java1.4及之后提供的一个非阻塞式的IO: 运用异步IO可通过少量线程处理大量请求。Tomcat8默认采用这种启动模式(ps:在Tomcat7里需要在修改配置文件来实现NIO)方式的启动。
APR模式是一种从操作系统层面来解决异步IO问题的方案, 可以大幅提高性能;之外我们还可以更改JVM栈内存,通过修改\tomcat server folder\bin\catalina.sh文件 添加一个
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8-server -Xms1024m -Xmx1024m-XX:NewSize=512m -XX:MaxNewSize=512m -XXermSize=512m-XX:MaxPermSize=512m -XX:+DisableExplicitGC"
二、Tomcat工作原理
Connector:接受客户端连接,加工处理客户端请求。就好比是tomcat的大门。Container:所有子容器的父接口。
tomcat默认三个端口就是这三个。当我们需要启动多个tomcat服务器实例时就需要修改里边的端口号,确保不会出现重复导致的端口监听冲突问题,对应server.xml文件的内容:
1)负责关闭tomcat服务器的端口号:8005
2)http请求端口:8080
3)与其他的http服务器建立链接:8009
Java体系结构:
三、调优
大致从以下三个方面来对Tomcat进行调优处理:内存优化、线程优化、配置优化,方向可选择:
采用动静分离节约tomcat的性能
调整tomcat的线程池
调整tomcat的连接器
修改tomcat的运行模式
禁用AJP连接器
3.1、基于JVM(内存)的优化
Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。我们可从以下2个方面来进行内存优化:1)Tomcat启动命令行中进行优化参数,即调优Jvm内存;2)Tomcat容器自身参数的优化
1)Tomcat启动命令行中的参数优化
Tomcat是跑在JVM之上的,它的启动实际就只是一个java命令行。它的启动参数位于tomcat的安装目录\bin目录下,如果你是Linux操作系统就是catalina.sh文件,如果你是Windows操作系统那么 则对应的是catalina.bat文件。打开该文件后,一般文件头部是一堆的由##包裹着的注释文字,如下:
文件末尾追加:
export JAVA_OPTS="-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true "
如果是windows:
set JAVA_OPTS=-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true
或者按如下精简配置也行:
Linux下追加:
JAVA_OPTS="-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx2048m
windows下追加:
set JAVA_OPTS=-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx2048m
参数说明:
-server:声明启用 JDK的 server 版本;这个参数是必须的,因tomcat默认是以一种叫java –client的模式来运行的,声明server后tomcat就以真实的production的模式在运行的,即tomcat以 server模式运行时将拥有:更大、更高的并发处理能力,更快更强捷的JVM垃圾回收机制,可以获得更多的负载与吞吐量等优良特性。
-Xms:Java虚拟机初始化时堆的最小内存,建议配置为与 Xmx配置为相同值,这样的好处是GC不必再为扩展内存空间而消耗性能;随着业务并发数越来越高,应用内存消耗将逐步上升,上升到Xmx后触发回落,当这种回落幅度较大时,将会导致CPU高速开始运转进行垃圾回收,此时严重的甚至会造成系统出现“卡壳”,网页会突然像卡死一样几秒甚至十几秒 时间,直到JVM垃圾回收完成,故我们多把这两个设成一样,以便Tomcat启动时堆大小就是最大化,充分利用系统,减少不一致性能问题。
-Xmx:Java虚拟机可使用堆的最大内存;
-Xmn:设置年轻代大小。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss:指定每个线程的堆栈大小。配置时需要依据实际的应用程序,估算一个线程大约需要占用多少内存,可能会有多少线程同时运行等。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。一般不宜设置超过1M,否则可能容易出现out ofmemory。
-XX:+AggressiveOpts:作用如其名(aggressive:积极),启用这个参数,则每当JDK版本升级时,你的JVM都会应用最新jdk相关的优化功能。
-XX:+UseBiasedLocking:启用一个优化了的线程锁,我们知道在我们的appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁将会使得你的appserver内对线程处理自动进行最优调配。
-XX:PermSize:Java虚拟机永久代大小;一般与-XX:MaxPermSize配合使用
-XX:MaxPermSize:Java虚拟机永久代大小最大值;-XX:PermSize=128M -XX:MaxPermSize=256M,JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。在数据量很大的文件导出时,一定要把这两个值设置上,否则会出现内存溢出的错误。
注意:配置堆内存最大值后,可执行下面的命令进行验证:
#java -Xmx2048m -version //如能正常显示出版本信息,即表明当前最大值配置正确可用,否者会报错
-XX:+DisableExplicitGC:在程序代码中不允许有显式的调用”System.gc()”。如果只是认为工程中每次在DAO操作结束时手动调用System.gc()一下,这样好像能够解决它们的out ofmemory问题,付出的代价就是系统响应时间严重降低,这样去调用GC会导致系统的JVM运行非常不稳