tomcat是我们常用的web容器,它的性能高低直接影响到应用对外提供服务的能力和用户的体验,所以tomcat的优化至关重要。对于单台tomcat服务器而言,优化主要是两方面:内存优化和配置优化(例如,连接数,线程池,iO等),当然还有使用tomcat原生库。除了这些tomcat本身固有配置优化,还有一些减少占用tomcat连接时间的配置,比如数据压缩。如果单个服务器经过优化后依然无法满足,性能要求,这时服务器集群就是必须的手段了,下面针对这些方面的优化详细介绍。
内存优化
主要是针对jvm各个内存大小的分配进行优化,以提高内存的使用率和减少资源变化带来的时间消耗。有关文件:catalina.sh(linux下)或者catalina.bat(window下)。
注意:对于32位操作系统上对jvm的内存有不能超过2G的限制,但是64位系统上没有这个限制。但很多情况下32操作系统上jvm的最大使用内存是不到2G的,2G只是个理想值,根据服务器的配置不同,可能有些只能用1500M或者1700M。具体支持多少,可以在控制台输入:java -Xmx2089M -version,如果出现Java版本,说明你的jvm内存可以设置到2089M。
Linux系统中tomcat的启动参数:
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系统中tomcat的启动参数:
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
这个参数必须加上,因为tomcat默认是以一种叫java –client的模式来运行的,server即意味着你的tomcat是以真实的production的模式在运行的,这也就意味着你的tomcat以server模式运行时将拥有:更大、更高的并发处理能力,更快更强捷的JVM垃圾回收机制等。
Xms是JVM初始化时的内存大小;Xmx是jvm的最大内存大小。Xms默认是物理内存的1/64,Xmx默认是物理内存的1/4,建议是物理内存的80%,但是一般我们会把Xms和Xmx设置一样大,这样在服务器启动时就是最大值可以避免内存膨胀和回落时带来的资源的消耗。特别是回落时会带来cpu的高速运转进行垃圾回收,系统可能会出现几秒甚至几十秒的卡顿现象。
Xmn是年轻代大小。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程 大约需要占用多少内存,可能会有多少线程同时运行等。一般不易设置超过1M,要不然容易出现out ofmemory。
作用如其名(aggressive),启用这个参数,则每当JDK版本升级时,你的JVM都会使用最新加入的优化技术(如果有的话)
启用一个优化了的线程锁,我们知道在我们的appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁使得你的appserver内对线程处理自动进行最优调配。
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;在数据量的很大的文件导出时,一定要把这两个值设置上,否则会出现内存溢出的错误。由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。那么,如果是物理内存4GB,那么64分之一就是64MB,这就是PermSize默认值,也就是永生代内存初始大小;四分之一是1024MB,这就是MaxPermSize默认大小。
在程序代码中不允许有显示的调用”System.gc()”。看到过有两个极品工程中每次在DAO操作结束时手动调用System.gc()一下,觉得这样做好像能够解决它们的out ofmemory问题一样,付出的代价就是系统响应时间严重降低,就和我在关于Xms,Xmx里的解释的原理一样,这样去调用GC导致系统的JVM大起大落,性能不到什么地方去哟!
对年轻代采用多线程并行回收,这样收得快。
即CMS gc,这一特性只有jdk1.5即后续版本才具有的功能,它使用的是gc估算触发和heap占用触发。
我们知道频频繁的GC会造面JVM的大起大落从而影响到系统的效率,因此使用了CMS GC后可以在GC次数增多的情况下,每次GC的响应时间却很短,比如说使用了CMS GC后经过jprofiler的观察,GC被触发次数非常多,而每次GC耗时仅为几毫秒。
设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。
这个值的设置是根据本地的jprofiler监控后得到的一个理想的值,不能一概而论原搬照抄。
在使用UseParNewGC 的情况下, 尽量减少 mark 的时间
在使用concurrent gc 的情况下, 防止 memoryfragmention, 对live object 进行整理, 使 memory 碎片减少。
指定 Java heap的分页页面大小
get,set 方法转成本地代码
指示只有在 oldgeneration 在使用了初始化的比例后concurrent collector 启动收集
CMSInitiatingOccupancyFraction,这个参数设置有很大技巧,基本上满足(Xmx-Xmn)*(100- CMSInitiatingOccupancyFraction)/100>=Xmn就不会出现promotion failed。在我的应用中Xmx是6000,Xmn是512,那么Xmx-Xmn是5488兆,也就是年老代有5488 兆,CMSInitiatingOccupancyFraction=90说明年老代到90%满的时候开始执行对年老代的并发垃圾回收(CMS),这时还 剩10%的空间是5488*10%=548兆,所以即使Xmn(也就是年轻代共512兆)里所有对象都搬到年老代里,548兆的空间也足够了,所以只要满 足上面的公式,就不会出现垃圾回收时的promotion failed;
因此这个参数的设置必须与Xmn关联在一起。
这个参数一般我们都是放在最后使用的,这全参数的作用是这样的,有时我们会在我们的J2EE工程中使用一些图表工具如:jfreechart,用于在web网页输出GIF/JPG等流,在winodws环境下,一般我们的app server在输出图形时不会碰到什么问题,但是在linux/unix环境下经常会碰到一个exception导致你在winodws开发环境下图片显示的好好可是在linux/unix下却显示不出来,因此加上这个参数以免避这样的情况出现。
配置优化
主要是优化conf/server.xml文件中相关配置参数。
这里主要是优化connector标签中的相关参数,用于处理访问的请求;当然此标签中也可以设置线程的相关参数,但是为了更好的性能一般我们使用外部的线程池,这样有利于线程的复用,以减少线程的创建和销毁带来的资源消耗;另外,我们也可以修改tomcat的运行模式:BIO,NIO,AIO(NIO2),APR.
AJP连接器:
用于将Apache与Tomcat集成在一起,当Apache接收到动态内容请求时,通过在配置中指定的端口号将请求发送给在此端口号上监听的AJP连接器组件。
属性:
backlog:当所有可能的请求处理线程都在使用时,队列中排队的请求最大数目。默认为10,当队列已满,任何请求都将被拒绝
maxSpareThread:允许存在空闲线程的最大数目,默认值为50
maxThread:最大线程数,默认值为200
minSpareThreads:设当连接器第一次启动时创建线程的数目,确保至少有这么多的空闲线程可用,默认值为4
port:服务端套接字的TCP端口号,默认值为8089(必须)
topNoDelay:为true时,可以提高性能,默认值为true
soTimeout:超时值
例:
<!—Define an AJP1.3 Connector on port 8089-->
<Connector port=”8089” enableLookups=”false” redirectPort=”8443” protocol=”AJP/1.3” />
AJPv13协议是面向包的。WEB服务器和Servlet容器通过TCP连接来交互;为了节省SOCKET创建的昂贵代价,WEB服务器会尝试维护一个永久TCP连接到servlet容器,并且在多个请求和响应周期过程会重用连接。我们一般是使用Nginx+tomcat的架构,所以用不着AJP协议,所以把AJP连接器禁用。
2.Connector标签常见参数的配置:
<Connector port="8080" protocol="HTTP/1.1"
//编码格式
URIEncoding="UTF-8"
//线程配置
maxThreads="1000" maxProcessors="1000" minProcessors="5" minSpareThreads="100" maxSpareThreads="1000
//连接数配置
maxConnections="1000"
connectionTimeout="20000" acceptCount="1000"
//是否关闭DNS的反响查询 false:关闭,true:开启
enableLookups="false"
//是否保持长时间连接,false:关闭,ture:开启
disableUploadTimeout="true"
//是否开启对url进行校验的配置 ,false:关闭,true:开启
useURIValidationHack="false"
//启用压缩的配置
compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
//post请求提交最大大小
maxPostSize="10485760"
acceptorThreadCount="8"
redirectPort="8443" />
(1)BIO:BIO(Blocking I/O),顾名思义,即阻塞式I/O操作,表示Tomcat使用的是传统的Java I/O操作(即java.io包及其子包)。Tomcat在默认情况下,是以bio模式运行的。遗憾的是,就一般而言,bio模式是三种运行模式中性能最低的一种。BIO配置采用默认即可。
(2)NIO:NIO(New I/O),是Java SE 1.4及后续版本提供的一种新的I/O操作方式(即java.nio包及其子包)。Java nio是一个基于缓冲区、并能提供非阻塞I/O操作的java API,因此nio也被看成是non- blocking I/O的缩写。它拥有比传统I/O操作(bio)更好的并发运行性能。要让Tomcat以nio模式来运行也比较简单,我们只需要protocol类型修改为:
//NIO
protocol="org.apache.coyote.http11.Http11NioProtocol"
//NIO2
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
即可。
(3)APR:APR(Apache Portable Runtime/Apache可移植运行时),是Apache HTTP服务器的支持库。你可以简单地理解为:Tomcat将以JNI的形式调用 Apache HTTP服务器的核心动态链接库来处理文件读取或 网络传输操作,从而大大地提高 Tomcat对静态文件的处理性能。
与配置 NIO运行模式一样,也需要将对应的 Connector节点的 protocol属性值改为:protocol="org.apache.coyote.http11.Http11AprProtocol"
相关APR介绍及配置会在下面专门讲。
当然Connector标签中的参数还有很多,这是只是常见的参数设置;并且这些中的参数也不一定都要设置,需要根据项目的具体情况去设置。
在介绍Connector标签中我们看到已经有线程的相关参数的设置,为什么还要有线程池?其实这个和Java中的线程池是一个道理,使用线程池可以使多连接公用线程,避免线程的频繁的创建和销毁带来的资源消耗。
引入线程池的方法,使用Connector标签中的executor的属性,将其值设置为Executor标签的name的值。例如:
<Connector port="8066" executor="tomcatThreadPool" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" enableLookups="false" maxPostSize="10485760" URIEncoding="UTF-8" useBodyEncodingForURI="true"
acceptCount="100" acceptorThreadCount="2" disableUploadTimeout="true" maxConnections="10000" SSLEnabled="false" />
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="1000" minSpareThreads="100" maxIdleTime="60000" maxQueueSize="Integer.MAX_VALUE" prestartminSpareThreads="false" threadPriority="5" className="org.apache.catalina.core.StandardThreadExecutor"/>
压缩
tomcat原生库
原文:https://www.cnblogs.com/htyj/p/10491282.html