Tomcat 调优总结

一. jvm参数调优

   常见的生产环境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 "

 

 

  -server 

 如果tomcat是运行在生产环境中的,这个参数必须加上,-server参数可以使tomcat以server模式运行,这个模式下将拥有:更大、更高的并发处理能力,更快更强捷的JVM垃圾回收机 制,可以有更大的负载与吞吐量

-Xms<size>和-Xmx<size>  
      前者表示JVM初始化堆的大小,后者表示JVM堆的最大值。一般认为把Xms与Xmx两个值设成一样是最优的做法,否则会导致jvm有较为频繁的GC,影响系统性能。因此一开始我们就把这两个设成一样,使得Tomcat在启动时就为最大化参数充分利用系统的效率。 如何确定当前OS jvm最大可用内存呢?在命令行下执行    

java -Xmx2048 -version

 

   命令,如果提示下图的信息,则证明当前内存数可以用

   

 

   如果提示下面的错误,则当前数值不可用.

    

 

 

-Xss

 

    设定每个线程的堆栈大小。依据具体应用,看一个线程大约占用多少内存、有多少线程同时运行等。一般不宜设置超过1M,要不然容易出现out ofmemory

–Xmn

    设置年轻代大小为512m。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun   官方推荐配置为整个堆的3/8。

 

 

-XX:+AggressiveOpts

 

  启用这个参数,则每当JDK版本升级时,你的JVM都会使用最新加入的优化技术(如果有的话)

-XX:+UseBiasedLocking

  启用一个优化了的线程锁。对于应用服务器(ApplicationServer)来说每个http请求就是一个线程,由于请求需要的时长不一,在并发较大的时候会有请求排队、甚至还会出现线程阻塞的现象,这个配置可以改善这个问题。

-XX:PermSize 和 -XX:MaxPermSize

  JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;使用XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

  XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError,说说为什么会内存益出: 

(1)这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同。 
(2)GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。
  这种错误常见在web服务器对JSP进行pre compile的时候。  

XX:+DisableExplicitGC

在程序代码中不允许有显示的调用”System.gc()”。

-XX:+UseParNewGC

  对年轻代采用多线程并行回收,这样收得快。

-XX:+UseConcMarkSweepGC

  即CMS gc,这一特性只有jdk1.5即后续版本才具有的功能,它使用的是gc估算触发和heap占用触发。
     我们知道频频繁的GC会造面JVM的大起大落从而影响到系统的效率,使用了CMS GC后可以在GC次数增多的情况下使每次GC的响应时间却很短。

-XX:MaxTenuringThreshold

设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。
如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。
这个值的设置是根据本地的jprofiler监控后得到的一个理想的值,不能一概而论原搬照抄。

 -XX:+CMSParallelRemarkEnabled

  在使用UseParNewGC 的情况下, 尽量减少 mark 的时间

-XX:+UseCMSCompactAtFullCollection

  在使用concurrent gc 的情况下, 防止 memoryfragmention, 对live object 进行整理, 使 memory 碎片减少。

-XX:LargePageSizeInBytes

  指定 Java heap的分页页面大小

-XX:+UseFastAccessorMethods

  get,set 方法转成本地代码

-XX:+UseCMSInitiatingOccupancyOnly

  指示只有在 oldgeneration 在使用了初始化的比例后concurrent collector 启动收集

-XX:CMSInitiatingOccupancyFraction=70

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关联在一起。

-Djava.awt.headless=true

这个参数一般我们都是放在最后使用的,这全参数的作用是这样的,有时我们会在我们的J2EE工程中使用一些图表工具如:jfreechart,用于在web网页输出GIF/JPG等流,在winodws环境下,一般我们的app server在输出图形时不会碰到什么问题,但是在linux/unix环境下经常会碰到一个exception导致你在winodws开发环境下图片显示的好好可是在linux/unix下却显示不出来,因此加上这个参数以免避这样的情况出现。

-Dsun.net.client.defaultConnectTimeout=60000

      连接建立超时设置

-Dsun.net.client.defaultReadTimeout=60000

     内容获取超时设置

-Djmagick.systemclassloader

    生成缩略图的一个框架的配置=60000

-Dnetworkaddress.cache.ttl=300

    jvm dns缓存超时的设置

-Dsun.net.inetaddr.ttl=300

  jvm dns缓存超时的设置

 

 

 

二 .tomcat配置优化

 

 

在tomcat的server.xml中有类似:    

<Connector port="80" protocol="HTTP/1.1" 
    connectionTimeout="60000" 
    redirectPort="8443"
    maxThreads="5000" 
    acceptCount="500"
    minSpareThreads="100"
    maxSpareThreads="5000"
    enableLookups="false"
    compression="on"
    compressionMinSize="2048"
    compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
    disableUploadTimeout="true"
    URIEncoding="UTF-8"/>

的配置, 其中: 

 

port:   服务端口

protocol:  服务协议

connectionTimeout:  超时时间单位是ms,并发要求高的话,将此值减少!

redirectPort:   重定向端口 需要安全通信的场合,将把客户请求转发至SSL的redirectPort端口 

      acceptCount:  当指定的连接数被用尽时,可放到出列队列中的数量,也即可接受的排队数量.    

maxThreads:   Tomcat可创建的最大的线程数(每一个线程对应一个请求), maxThreads决定了tomcat的最大线程阀值,需要设置的大一些

minSpareThreads:   最小备用(空闲)线程数

maxSpareThreads:   最大备用(空闲)线程数,如果空闲线程超过这个值,Tomcat就会关闭不活动线程;

enableLookups:  关闭DNS查询

URIEncoding:   设置tomcat默认的转码格式 查看$TOMCAT_HOME/webapps/tomcat-docs/config/http.html这个说明文档,有如下说明: 

  URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used. 

  也就是说,如果没有设置URIEncoding, Tomcat默认是按ISO-8859-1进行URL解码,ISO-8859-1并未包括中文字符,这样的话中文字符肯定就不能被正确解析了。

 useURIValidationHack:  如果把useURIValidationHack设成"false",可以减少它对一些url的不必要的检查从而减省开销。

       disableUploadTimeout:       

       maxKeepAliveRequests: 
        表示该连接最大支持的请求次数。超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端)
     keepAliveTimeout:
    表示在下次请求过来之前,tomcat保持该连接多久。这就是说假如客户端不断有请求过来,且每次连接间隔不超过这个值设置的时间,则该连接将一直保持。 

       compression、compressionMinSize、 compressableMimeType:omcat配置gzip压缩(HTTP压缩)功能   

1)compression="on" 打开压缩功能

2)compressionMinSize="2048" 启用压缩的输出内容大小,这里面默认为2KB

3)noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩

4)compressableMimeType="text/html,text/xml" 压缩类型

 

在实现中,我们发现使用该配置,连接数上去之后很难下降,导致CPU一直维持在一个比较高的水平. 后来我们换了一种连接方式,采用线程池的方式,首先定义一个Executor: 

<Executor name="tomcatThreadPool" 
        namePrefix="tomcatThreadPool-" 
        maxThreads="1000" 
        maxIdleTime="300000"
        minSpareThreads="200"/>

参数的意义和上述相同 ,在Connector中使用定义的这个连接池:  

<Connector executor="tomcatThreadPool"
           port="20003" protocol="HTTP/1.1"
           acceptCount="800"
           minProcessors="300"
           maxProcessors = "1000"
           redirectPort="8443"/>

此处 minProcessors  参数对应前一种配置方式中的minSpareThreads, maxProcessors则与maxThreads意义差不多. 

使用连接池以后: 发现连接数上升之后如果一段时间内请求数下降了,连接数会很快下降,CPU的消耗也会随之下降,处理能力得到了增强.

 

补充:

如何查看当前tomcat的连接数呢?

假设服务器上开启了 2个tomcat实例,分别监听8040和8050端口

netstat -na | grep ESTAB | grep 8040 | wc -l
netstat -na | grep ESTAB | grep 8050 | wc -l

二者之和,就是所有tomcat的连接数

 

 



 

posted on 2013-06-25 14:26  babyblue  阅读(4313)  评论(0编辑  收藏  举报