Tomcat 性能优化的必要
Tomcat 作为当前主流的中小 Java WEB 应用容器,或者通过集群的方式部署,也能运行中大 Java WEB 应用。如果仅仅使用 Tomcat 默认的配置,无法发挥 Tomcat 最大的性能。
Tomcat 初始默认的内存为128M,这在部分中大 Java WEB 应用中,内存存在明显偏小的情况。这时需要结合服务器物理实际情况配置相关参数来优化 Tomcat 性能。一般情况下,将堆的最大值设为可用内存的70%-80%左右,因为当应用程序需要的内存超出堆的最大值时虚拟机就会导致内存溢出,应用崩溃。
内存优化
直接修改 Java 虚拟机运行时候启动参数,在启动文件前添加 JAVA_OPTS 属性
- Windows:Tomcat 安装目录/bin/catalina.bat
- Linux:Tomcat 安装目录/bin/catalina.sh
在文件前添加如下配置:
JAVA_OPTS='-Xms 64M -Xmx 128M -XX:PermSize=64M -XX:MaxPermSize=128M'
部分选项说明:
- -server:启动 Java 虚拟机服务器版本,提高 Java 虚拟机性能,如果服务器安装的64位 Java 环境,不支持 client 模式,默认启动就是 server模式,如果是32位 Java 环境,建议开启 server 模式;
- -Xss:设置Java线程栈的值;
- -Xms:设置Java堆的初始化大小;
- -Xmx:设置Java堆的最大值;
- -XX:PermSize:内存最小永久保留区域,该区域不会被垃圾回收器回收;
- -XX:MaxPermSize:内存最大永久保留区域,该区域不会被垃圾回收器回收;
- Xmn:Java虚拟机最小使用内存;
- Xshare:设定类数据共享CDS(Class data sharing)是否开启,该选择有三个值 on off auto;
- -Xnoclassgc:禁用Java垃圾回收器;
- -Xincgc:启用Java增量式垃圾回收器;
- -Xmixed:解释模式和编译模式混合执行;
- -Xcheck:jni:针对JNI函数做额外的检查。
需要注意的是:-XX:PermSize 和 -XX:MaxPermSize,是非标准可选项(Nonstandard Options),不能保证在所有平台上都能生效。
Tomcat 线程优化
打开 Tomcat 配置文件 server.xml
<Connector port="80" protocol="HTTP/1.1" maxThreads="600" minSpareThreads="100" maxSpareThreads="500" acceptCount="700"
connectionTimeout="20000" />
属性说明:
- maxThreads:最大同时处理的连接数,默认值150,该数值不能设置的过大,一般尽量不要超过8000,如果你的网站访问量非常大可运行多个 Tomcat 实例;
- minSpareThreads:Tomcat 启动时初始化的连接数,默认值25;
- maxSpareThreads:Tomcat 最大线程连接数,超过该数值,Tomcat 就开始关闭不需要的线程,默认值75;
- acceptCount:当连接超过 maxThreads 时,连接等候的队列数,如果队列超过这个数值的请求将不会处理,默认值10;
- connectionTimeout:连接超时时间,默认值60000,单位是ms,0代表用不超时;
- enableLookups:是否开启反查域名,默认值是true;
- maxKeepAliveRequests:保持请求数,默认值100;
- compression:压缩传输 有三个值 on off force,默认值off。
Tomcat IO 优化
三种 IO 方式介绍
- BIO(同步阻塞IO):服务器实现模式为一个连接一个线程(One Connection One Thread),可通过线程池机制改善频繁创建关闭线程对服务器资源的消耗;
- NIO(异步阻塞IO):服务器实现模式为一个请求一个线程(One Request One Thread),可以达到多个连接共用一个线程;
- AIO(异步非阻塞IO):通过操作系统底层来实现异步操作。
三种 IO方式适用场景 - BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高;
- NIO方式适用于连接数目多且连接比较短(轻操作)的架构;
- AIO方式使用于连接数目多且连接比较长(重操作)的架构。
打开 Tomcat 配置文件 server.xml
<Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
URIEncoding="UTF-8"
useBodyEncodingForURI="true"
enableLookups="false"
redirectPort="8443" />
其中将属性 protocol 从 HTTP/1.1 修改为 org.apache.coyote.http11.Http11NioProtocol,就可以启用 Tomcat 自带的 NIO 模型。
使用 APR 来提高 Tomcat 性能
Tomcat可以使用APR来提供超强的可伸缩性和性能,更好地集成本地服务器技术。
APR(Apache Portable Runtime)是一个高可移植库,它是Apache HTTP Server 2.x的核心。APR有很多用途,包括访问高级IO功能(例如sendfile,epoll和OpenSSL),OS级别功能(随机数生成,系统状态等等),本地进程管理(共享内存,NT管道和UNIX sockets)。这些功能可以使Tomcat作为一个通常的前台WEB服务器,能更好地和其它本地web技术集成,总体上让Java更有效率作为一个高性能web服务器平台而不是简单作为后台容器。
在产品环境中,特别是直接使用Tomcat做WEB服务器的时候,应该使用Tomcat Native来提高其性能。
APR 官网:http://apr.apache.org/
也可以安装Apache Tomcat Native Library,直接启动就支持APR,它本身是基于APR的。
Apache Tomcat Native Library 官网:http://tomcat.apache.org/native-doc/
Apache Tomcat Native Library 安装
Apache Tomcat Native Library 依赖于以下组件:
- APR library
- OpenSSL libraries
- Java SE Development Kit (JDK)
安装依赖组件:
yum install -y apr-devel openssl-devel
下载 Tomcat Native 源码:
下载地址:http://tomcat.apache.org/download-native.cgi
解压编译安装 Tomcat Native:
cd /opt/tomcat/bin
tar -zxvf tomcat-native.tar.gz
cd tomcat-native-1.2.12-src/native
./configure --with-apr=$HOME/APR --with-java-home=$JAVA_HOME --with-ssl=$HOME/OPENSSL --prefix=$CATALINA_HOME
make && make install
说明:
- $HOME/APR:APR 安装路径,常见默认安装路径:/usr/bin/apr-1-config;
- $JAVA_HOME:Java安装路径;
- $HOME/OPENSSL:OPENSSL安装路径;
- $CATALINA_HOME:Tomcat安装路径。
配置
打开 server.xml,添加 AprLifecycleListener 监听器
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
编辑 $CATALINA_HOME/bin/setenv.sh 如果没有该文件,可以新建该文件
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CATALINA_HOME/lib
export LD_LIBRARY_PATH
启动 Tomcat 服务器,如果看到类似以下内容就安装成功
Feb 8, 2017 12:27:41 PM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.x.y.
Feb 8, 2017 12:27:41 PM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Feb 8, 2017 12:27:41 PM org.apache.coyote.http11.Http11AprProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
其它优化
使用多实例单应用方式部署
使用多实例单应用可以最大程度的保证每个应用之间的独立性,任何一个应用的崩溃、重启、关闭均不会影响到其它应用。
关闭 Tomcat 压错传输
在 Tomcat 可以开启gzip,修改 server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
compression="on"
compressionMinSize1="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,,application/octet-stream"/>
但是,压缩会增加Tomcat负担,应该将压缩的事情交由 Nginx 或者 Apache 去处理。
关闭 Tomcat HTTPS传输
利用 Tomcat 开启 HTTPS 传输,修改 server.xml
<Connector port="443" maxHttpHeaderSize="8192"
maxThreads="150"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
SSLEnabled="true"
SSLCertificateFile="SSL证书文件路径"
SSLCertificateKeyFile="SSL私匙路径" />
和压缩类似的情况,HTTPS也会增加Tomcat负担,应该将HTTPS的事情交由 Nginx 或者 Apache 去处理。
禁用 DNS 查询
当web应用程序记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名 转换为IP地址。
DNS查询需要占用网络,并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。
修改 server.xml 文件中的 Connector 元素,修改属性 enableLookups 参数值为 false 。
如果 enableLookups 值为 true,则可以通过调用 request.getRemoteHost() 进行DNS查询来得到远程客户端的实际主机名,若为 false 则不进行DNS查询,而是返回客户端 ip地址 。
设置 session 过期时间
在一般应用客户端登录后,都会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动退出登录,销毁session。
有三种方式来设置Session过期时间
- 在 Tomcat 的 web.xml 中进行设置
<session-config>
<session-timeout>30</session-timeout>
</session-config>
单位为分钟
- 在应用的 web.xml 中进行设置
<session-config>
<session-timeout>30</session-timeout>
</session-config>
单位为分钟
- 在应用中通过代码进行设置
session.setMaxInactiveInterval(30*60);
单位为秒,这里的设置为过期时间为30分钟
这三种方式将按照下面的顺序优先执行:
- 通过应用代码设置
- 通过应用的 web.xml 设置
- 通过 Tomcat 中的 web.xml 设置
本文部分内容参考以下网址: