tomcat是我们在web开发中应用较为广泛的web应用服务器,之所以使用其作为web应用服务器是因为其即可以实现html等静态文件的访问(web服务器),又实现了servlet能处理动态web请求(web容器),这里与nginx有一个地方不同,nginx可以转发请求,也可以实现静态文件访问,但是其并不可以作为servlet容器,通常情况下,我们的我们服务在一定的硬件资源的前提下需要提高应用可支持的并发量就需要做一些优化,下面就简单的谈谈tomcat在现实生产中的相关调优,这种文章在网上很多,个人也是根据平时涉及的和了解的做个总结。
并发优化:
1.硬件资源
如果条件允许可以适当增加服务器的硬件资源,毕竟相对于参数配置,增加硬件资源更简单
2.参数优化
修改JVM相关配置linux修改/bin/catalina.sh,win下修改bin/catalina.bat
(linux)JAVA_OPTS="-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx2048m"
(win)set JAVA_OPTS=-server -XX:PermSize=512M -XX:MaxPermSize=1024m -Xms2048m -Xmx2048m
参数介绍
-server 启用jdk的server版本
-Xms java虚拟机初始化堆的最小内存
-Xmx java虚拟机可使用堆的最大内存(一般和Xms一样大,这样这样因为最大和最小一样大,GC不会扩展内存空间,从而减小一本开支)
-XX:PermSize java虚拟机永久代大小
-XX:MaxPermSize java虚拟机永久代最大值
可以使用jps 查看java本地进程等和jmap查看JVM物理内存占用情况等,或者visualVm来查看划分的内存区域大小
3.连接(并发)优化
Connector优化:Connector是连接器,负责接收客户的请求,以及向客户端回送响应消息,默认情况下tomcat支持200线程访问,如果超出200则其他线程将是等待状态甚至是超时。
找到conf下的server.xml,找到<Connector />,贴出配置
<Connector port="8080" protocol="HTTP/1.1" maxThreads="1000" minSpareThreads="100" acceptCount="1000" maxConnections="1000" connectionTimeout="20000" maxHttpHeaderSize="8192" tcpNoDelay="true" compression="on" compressionMinSize="2048" disableUploadTimeout="true" redirectPort="8443" enableLookups="false" URIEncoding="UTF-8" />
参数解释:
maxThreads:连接器创建处理请求线程的最大数目,处理同事请求的最大数目,默认值为200。
minSpareThreads:线程的最小运行数目,这些始终保持运行。如果未指定,默认值为10。
acceptCount:最大队列长度。一般与maxThreads相同,默认为100。
maxConnections:在任何给定的时间内,服务器将接受和处理的最大连接数。当这个数字已经达到时,服务器将接受但不处理,等待进一步连接。NIO与NIO2的默认值为10000,APR默认值为8192。
connectionTimeout:当请求已经被接受,但未被处理,也就是等待中的超时时间。单位为毫秒,版本不同默认值可能存在不同,一般为20000,这个值可能影响你的正常请求的处理,比如一个请求处理时间超过20S就会出问题。
maxHttpHeaderSize:请求和响应的HTTP头的最大大小,以字节为单位指定。如果没有指定,这个属性被设置为8192(8 KB),过大会导致请求流量增大。
tcpNoDelay:如果为true,服务器socket会设置TCP_NO_DELAY选项,在大多数情况下可以提高性能。缺省情况下设为true,也就是你不设置它也是true。
compression:是否启用gzip压缩,默认为关闭状态。这个参数的可接受值为“off”(不使用压缩),“on”(压缩文本数据),“force”(在所有的情况下强制压缩),压缩有助于减小网络资源占用。
compressionMinSize:如果compression="on",则启用此项。被压缩前数据的最小值,也就是超过这个值后才被压缩。如果没有指定,这个属性默认为“2048”(2K),单位为byte。
disableUploadTimeout:这个标志允许servlet Container在一个servlet执行的时候,使用一个不同的,更长的连接超时。最终的结果是给servlet更长的时间以便完成其执行,或者在数据上传的时候更长的超时时间。如果没有指定,设为false。
enableLookups:关闭DNS反向查询,这个个人理解意思是服务器会记录访客的ip的信息,会通过域名等或者直接拿到IP,其会占用一定的带宽资源,但是,我没有理解这里的记录是服务器的记录,还是我们的应用中记录(比如useragent的信息),有谁知道的可以告知下,有空自己测试下。
4. IO优化
Tomcat 连接器的三种方式: bio、nio 和 apr,三种方式性能差别很大,apr 的性能最优, bio 的性能最差。而 Tomcat 7 使用的 Connector 默认就启用的 Apr 协议,但需要系统安装 Apr 库,否则就会使用 bio 方式。
1:同步阻塞IO(JAVA BIO) 同步并阻塞,服务器实现模式为一个连接一个线程(one connection one thread 想想都觉得恐怖,线程可是非常宝贵的资源),当然可以通过线程池机制改善.
2:JAVA NIO:又分为同步非阻塞IO,异步阻塞IO 与BIO最大的区别one request one thread.可以复用同一个线程处理多个connection(多路复用).
3:异步非阻塞IO(Java NIO2又叫AIO) 主要与NIO的区别主要是操作系统的底层区别.可以做个比喻:比作快递,NIO就是网购后要自己到官网查下快递是否已经到了(可能是多次),然后自己去取快递;AIO就是快递员送货上门了(不用关注快递进度)。
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解.
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持.
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持.
设置方法:protocol
5.开启线程池
相关参数说明:
name:线程池名称,用于 Connector中指定。
namePrefix:所创建的每个线程的名称前缀,一个单独的线程名称为 namePrefix+threadNumber。
maxThreads:池中最大线程数。
minSpareThreads:活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。
maxIdleTime:线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒。
maxQueueSize:在被执行前最大线程排队数目,默认为Int的最大值,也就是广义的无限。除非特殊情况,这个值不需要更改,否则会有请求不会被处理的情况发生。
prestartminSpareThreads:启动线程池时是否启动 minSpareThreads部分线程。默认值为false,即不启动。
threadPriority:线程池中线程优先级,默认值为5,值从1到10。
className:线程池实现类,未指定情况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。如果想使用自定义线程池首先需要实现 org.apache.catalina.Executor接口。
6.APR和tomcat native
APR可以极大的提高tomcat的性能,主要的使用提高io
一般默认是开启apr的listener的,但是我们的connect中还是需要修改protocol,有一点特别重要,上面提到过,开启apr需要安装其依赖包。
protocol="org.apache.coyote.http11.Http11AprProtocol"
PS:现在大多数开发都是使用微服务,而springboot内置了tomcat,但并不代表其不可以优化,大致思想和外部的tomcat是一致的,只是方式不同而已推荐可以看这篇文章https://www.jianshu.com/p/4ee2628b1cb5