一、Tomcat 调优大致分为两大类:
1️⃣Tomcat 的自身调优:
- 采用动静分离节约 Tomcat 的性能
- 禁用 AJP 连接器
- 调整 Tomcat 的线程池
- 调整 Tomcat 的连接器
- 修改 Tomcat 的运行模式
2️⃣JVM 的调优:调优 JVM 内存
二、Tomcat 自身调优
1️⃣采用动静分离
静态资源如果也让 Tomcat 处理的话,Tomcat 的性能会被损耗很多。所以一般都是采用:Nginx+Tomcat 实现动静分离。Nginx 实现静态资源的访问,让 Tomcat 只负责 jsp 文件的解析工作。
2️⃣禁用 AJP 连接器
AJP 的全称 Apache JServer Protocol。使用 Nginx+Tomcat 的架构,用不着 AJP,所以禁用。
- Linux 下修改 TOMCAT_HOME/bin/catalina.sh,在其中加入如下代码,可以放在 CLASSPATH = 下面:
JAVA_OPTS="-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx2048m"
- windows 下修改 TOMCAT_HOME/bin/catalina.bat,在其中加入如下代码,可以放在 set CLASSPATH = 下面:
set JAVA_OPTS=-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx2048m
参数说明:
- -server:启用 JDK 的 server 版本;
- -Xms:Java 虚拟机初始化时堆的最小内存,一般与 Xmx 配置为相同值,这样的好处是 GC 不必再为扩展内存空间而消耗性能;
- -Xmx:Java 虚拟机可使用堆的最大内存;
- -XX:PermSize:Java 虚拟机永久代大小;
- -XX:MaxPermSize:Java 虚拟机永久代大小最大值;
3️⃣调优 Tomcat 线程池
打开 tomcat 的 server.xml,配置 Executor,相关参数说明如下:
参数解释:
- name:给执行器(线程池)起一个名字
- namePrefix:指定线程池中的每一个线程的 name 前缀
- maxThreads:线程池中最大的线程数量
假设:请求的数量超过了“750”,这不是意味着将 maxThreads 属性值设置为“750”,它的最好解决方案是使用“Tomcat集群”。也就是说,如果有“1000”请求,两个 Tomcat 实例设置“maxThreads= 500”,而不是在单 Tomcat 实例的情况下设置 maxThreads=1000。 - minSpareThreads:线程池中允许空闲的线程数量(多余的线程都杀死)
- maxIdLeTime:一个线程空闲多久算是一个空闲线程
4️⃣调优 Tomcat 的连接器 Connector
打开 Tomcat 的 server.xml,(比较完整)配置 Connector,参数说明如下:
参数解释:
- executor:指定这个连接器所使用的执行器(线程池)。对应“Executor ”配置中的name值。
- enableLookups="false":关闭 DNS 解析,减少性能损耗。
- maxThreads="X" 表示最多同时处理 X 个连接。相当于最大线程数。
- minSpareThreads="X" 初始化 X 个连接。最小空闲线程数,这里是一直会运行的线程。
- acceptCount="X" 当同时连接的人数达到 maxThreads 时,还可以排队,队列大小为 X。超过 X 就不处理。
- maxSpareThreads="X" 表示如果最多可以有 X 个线程,一旦超过 X 个,则会关闭不再需要的线程。
- minProcessors:服务器启动时创建的最少线程数;
- maxProcessors:最大可以创建的线程数;
注意:
与压缩有关系的配置:如果已经对代码进行了动静分离,静态页面和图片等数据就不需要 Tomcat 处理了,那么也就不需要在 Tomcat 中配置压缩了。
5️⃣通过修改 Tomcat 的运行模式
同步阻塞IO (JAVA BIO)
Tomcat8 以下版本,默认使用的就是 BIO 模式。服务器实现模式为一个连接一个线程(one connection one thread),对于每一个请求都要创建一个线程来进行处理,不适合高并发。当然可以通过线程池机制改善。
同步非阻塞IO (JAVA NIO)
又分为异步阻塞 IO。与 BIO 最大的区别 one request one thread。可以复用同一个线程处理多个 connection(多路复用)。Tomcat8 以上版本,默认使用的就是NIO模式「非阻塞式 IO」。
异步非阻塞IO (Java NIO2又叫AIO)
与NIO的区别主要是操作系统的底层区别。可以做个比喻:比作快递,NIO就是网购后要自己到官网查下快递是否已经到了(可能是多次),然后自己去取快递;AIO就是快递员送货上门了(不用关注快递进度)。
适用:
BIO 方式适用于连接数目比较小且固定的架构。这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 以前的唯一选择,但程序直观简单易理解。
NIO 方式适用于连接数目多且连接比较短(轻操作)的架构。比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4 开始支持。
AIO 方式使用于连接数目多且连接比较长(重操作)的架构。比如相册服务器,充分调用 OS 参与并发操作,编程比较复杂,JDK7 开始支持。
在server.xml中:
实现对Tomcat的IO切换。
APR(Apache Portable Runtime)
APR 是一个高可移植库。它是 Apache HTTP Server 2.x 的核心,能更好地和其它本地 web 技术集成,总体上让 Java 更有效率作为一个高性能 web 服务器平台而不是简单作为后台容器。是 Tomcat 生产环境运行的首选方式,如果操作系统未安装 APR 或者 APR 路径未指到 Tomcat 默认可识别的路径,则 APR 模式无法启动,自动切换启动 NIO 模式。所以必须要安装 Apache Tomcat Native Library,直接启动就支持 APR,APR 是从操作系统级别解决异步 IO 问题,排除代码问题 Tomcat 优化到这个层次,可以大幅度的提高性能。APR 的本质就是使用 JNI 技术调用操作系统底层的 IO 接口,所以需要提前安装所需要的依赖。
在产品环境中,特别是直接使用 Tomcat 做 WEB 服务器的时候,应该使用 Tomcat Native 来提高其性能。如果不配 APR,基本上 300 个线程很快就会用满,以后的请求就只好等待。但是配上 APR 之后,并发的线程数量明显下降,从原来的 300 可能会马上下降到只有几十,新的请求会毫无阻塞的进来。
在局域网环境测,就算是 400 个并发,也是一瞬间就处理/传输完毕,但是在真实的 Internet 环境下,页面处理时间只占 0.1% 都不到,绝大部分时间都用来页面传输。如果不用 APR,一个线程同一时间只能处理一个用户,势必会造成阻塞。所以生产环境下用 APR 是非常必要的。
三、JVM 调优
Tomcat 是运行在 JVM 上的,所以对 JVM 的调优也是非常有必要的。启动时告诉 JVM 要一块大内存,调优内存是最直接的方式。调整堆大小的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。找到 catalina.sh:添加:
JAVA_OPTS='-Xms256m -Xmx512m'
完整参数设置:
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"
- -Xms
Java 虚拟机初始化时堆的最小内存,一般与 Xmx 配置为相同值,这样的好处是 GC 不必再为扩展内存空间而消耗性能; - -Xmx
Java 虚拟机可使用堆的最大内存。实际参数大小根据服务器配置或者项目具体设置。