一、总结前一天的学习从“Day3”的性能测试部分,我们了解到了几个决定性能测试的重要指标。分别是:ThroughputResponsetimeCpuloadMemoryUsage我们在研究过程中对Apache进行了优化,优化了以上四个核心指标的读数。那么我们的Apache调优好了,我们的Tomcat也相应的做了调整。课程结束后,到时候你的“小猫”就真的会“飞”起来了,请仔细阅读。这篇文章一方面是用来给曾经写过《Tomcat如何承受1000个用户》的人解释的,对作者的尊重,一方面是对原文章的扩展,因为申请后就解决了将原文章的知识应用于两个相关的重大项目:承载更大的并发用户数并取得良好的性能提升(系统平均性能提升20倍,极限事务可达80倍)。另外值得一提的是,当时我们在项目中使用的“小猫”是在32位机器上运行的,也就是我们的JVM受限于最大内存2GB,已经跑的“飞了”。.....如果你在64位机器下运行这只“小猫”。.....正如你所想象的,你会得到什么样的效果?请在下方详细设置!2.所有基于JVM的优化(内存)2.1JVM在32位操作系统和64位操作系统的对比我们一般的开发者基本都是使用32位的Windows系统,这就导致了一个比较严重的问题:32-的内存限制位Windows系统。先来看一张对照表:解决完以上问题,我们再相见。有一个新问题,JVM在32位系统下的内存限制:不能超过2GB内存,即使你的机器在Win2003AdvancedServer下配备8GB-16GB内存,而你的JAVA也只能使用2GB记忆。其实我一直想推荐大家使用Linux或者Mac操作系统,并且安装64位的,因为毕竟我们是用来开发的,不是用来玩游戏的,而且Java来自Unix,属于Unix(Linux仅在PC上运行。仅限Unix)。因此,很多开发者运行在win32位系统上,甚至在生产环境中部署win32位系统。那么这个时候如果要优化你的Tomcat,就必须要注意一些技巧。在64位操作系统上,系统内存和JVM都不受2GB这样的限制。Tomcat的优化分为两部分:Tomcat启动命令行中的优化参数为JVM优化。Tomcat容器本身参数的优化(这个和ApacheHttpServer很像)本节先讲Tomcat启动命令行中的参数优化。Tomcat首先运行在JVM上,因为它的启动实际上只是一个java命令行。首先,我们需要调优JAVA的启动命令行。需要注意的是,这里讨论的JVM优化是基于OracleSun的jdk1.6或以上版本,其他JDK或更低版本的JDK不适用。2.2Tomcat启动参数优化Tomcat的启动参数位于tomcat安装目录的in目录下。如果您使用的是Linux操作系统,则为catalina.sh文件。如果您使用的是Windows操作系统,您需要修改的是catalina.bat文件。打开文件,一般文件头是一堆##包裹的注释文字,找到最后一段注释文字如:#$Id:catalina.sh5227972007-03-2707:10:29Zfhanik$#-----------------------------------------------------------------------#OSspecificsupport.$var_must_besettoeithertrueorfalse。输入回车,在linux系统exportJAVA_OPTS="-server-Xms1400M-Xmx1400M-Xss512k-XX:+AggressiveOpts-XX:+UseBiasedLocking-XX:PermSize=128M-XX:MaxPermSize=256M-XX:+AggressiveOpts-XX:+UseBiasedLocking-XX:PermSize=128M-XX:MaxPermSize="-server-Xms1400M-Xmx1400M-Xss512k-XX="-server-Xms1400M-Xmx1400M-Xss512k-XX::+DisableExplicitGC-XX:MaxTenuringThreshold=31-XX:+UseConcMarkSweepGC-XX:+UseParNewGC-XX:+CMSParallelRemarkEnabled-XX:+UseCMSCompactAtFullCollection-XX:LargePageSizeInBytes=128m-XX:+UseFastAccessorMethods-XX:+UseCMSInitiating.DjaawlyOnlyheadless=true"tomcat启动参数setJAVA_OPTS1=-server0-XmsinWindows系统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启动命令中加入这么多参数,当然这些参数是只是我机器上的可能不适合你,尤其是参数后面的值(value)是一个需要根据你自己的实际情况设置的参数解释:-server我不管你是什么原因,只要你的tomcat是运行在生产环境的其中,这个参数是必须要加上的,因为tomcat默认运行在一个叫java-client的模式,server是指你的tomcat运行在真正的生产模式,也就是当你的tomcat运行在服务器模式下,它将拥有:更大更高的并发处理能力,更快更强大的JVM垃圾回收机制,更大的负载和吞吐量。..甚至。..和更多。..记住Y,不然这个-server加不上去,会被打屁股的。-Xms–Xmx是JVM内存设置。Xms和Xmx设置相同是最好的方法。有人说Xms是最小值,Xmx是最大值,不太好听。这样的设置更加人性化和科学化。改变。人性?科学?你的尺码。我们来思考这样一个场景:随着并发数的增加,系统的内存占用逐渐增加。当它到达最高点时,就不能再上升了,然后开始下降。不要认为这个秋天是好事,因为它是一个大起大落,当内存回落时,它付出的代价就是CPU开始高速运行进行垃圾回收。这时候,甚至会导致你的系统“卡死”。十几秒,因为JVM在垃圾回收。所以,我们一开始就把这两个设置成一样的,这样Tomcat就可以充分利用系统的效率,最大化启动时的参数。这个原因和jdbcconnectionpool中的minpoolsize和maxpoolsize是一样的。原则。我怎么知道我的JVM可以使用最大值?摸头?决不!在设置最大内存,也就是Xmx值的时候,请先打开一个命令行,输入如下命令:看,可以正常显示JDK的版本信息,说明这个可以用了。不是说32位系统最多可以使用2GB内存吗?即:2048m,我们可以试试吗?决不!不说2048m,试试1700m,1700m怎么样?2048m就更不用说了,2048m只是一个理论值,这么说吧,我这里有好几台机器,有的机器-Xmx1800没问题,有的机器只能到-Xmx1500m。所以,在设置-Xms和-Xmx值的时候,一定要记得先这样测试,不然你直接在tomcat启动命令行里加,你的tomcat就再也启动不起来了,不飞了想飞。这只是瘟疫猫。-Xmn将年轻代大小设置为512m。整个堆大小=新生代大小+老年代大小+永久代大小。永久代一般固定大小为64m,所以增加新生代会减小老年代的大小。这个值对系统性能影响很大,Sun官方推荐配置为整个堆的3/8。-Xss指的是设置每个线程的堆栈大小。这取决于你的程序,一个线程需要占用多少内存,可能有多少个线程同时运行等等。一般不容易设置超过1M,否则容易出现内存不足。-XX:+AggressiveOpts顾名思义(aggressive),启用这个参数,每当JDK版本升级时,你的JVM都会使用新添加的优化技术(如果有的话)-XX:+UseBiasedLocking启用优化的线程锁,我们知道那在我们的appserver中,每个http请求都是一个线程,有的请求短有的长,会出现请求排队的现象,甚至线程阻塞,这个优化过的线程锁让你在appserver中自动优化分配线程处理。-XX:PermSize=128M-XX:MaxPermSize=256MJVM使用-XX:PermSize设置非堆内存的初始值,默认为物理内存的1/64;导出数据量大的文件时,一定要设置好这两个Value设置,否则会出现内存溢出错误。最大非堆内存大小由XX:MaxPermSize设置,默认为物理内存的1/4。那么,如果物理内存是4GB,那么64的四分之一就是64MB,这是PermSize的默认值,也就是永久代内存的初始大小;四分之一是1024MB,这是MaxPermSize的默认大小。-XX:+DisableExplicitGC不允许在程序代码中显式调用“System.gc()”。我见过两个在DAO操作结束时手动调用System.gc()的优秀项目。我觉得这样做似乎可以解决他们的内存不足问题。付出的代价是系统响应时间严重降低,就像我在Xms和Xmx中讲解的原理一样。这样调用GC会导致系统的JVM波动很大,性能也上不去!-XX:+UseConcMarkSweepGC是CMSgc。该功能仅在jdk1.5及以后的版本中有。它使用了gc估计触发器和堆占用触发器。我们知道频繁的GC会因为JVM的起伏而影响系统的效率。因此,使用CMSGC后,当GC数量增加时,每次GC的响应时间可以很短。比如使用CMSGC,通过jprofiler观察,GC被触发的次数非常多,每次GC只需要几毫秒。-XX:MaxTenuringThreshold设置垃圾最大年龄。如果设置为0,新生代对象将直接进入老年代,不经过Survivor区。对于老年代较多的应用,可以提高效率。如果该值设置较大,新生代对象会在Survivor区被多次复制,可以增加对象在新生代的存活时间,增加在新生代被回收的概率。该值的设置是本地jprofiler监控后得到的一个理想值,不能一概而论,照搬原样。-XX:+CMSParallelRemarkEnabled使用UseParNewGC时,最小化标记时间-XX:+UseCMSCompactAtFullCollection使用并发gc时,防止内存碎片,组织存活对象,减少内存碎片。-XX:LargePageSizeInBytes指定Java堆的分页页大小-XX:+UseFastAccessorMethodsget,set方法转换为本地代码-XX:+UseCMSInitiatingOccupancyOnly表示只有老年代使用初始化比例时,并发收集器才开始收集-XX:CMSInitiatingOccupancyFraction=70CMSInitiatingOccupancyOccion,设置这个参数有很多技巧,基本满足(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn就不会导致提升失败。在我的应用中,Xmx为6000,Xmn为512,那么Xmx-Xmn为5488兆,即老年代有5488兆,CMSInitiatingOccupancyFraction=90表示老年代90%满时开始执行并发垃圾回收(CMS),此时剩余的10%空间为5488*10%=548兆,所以即使把Xmn中的所有对象(也就是年轻代的512兆)全部移动到老年代generation,548兆字节空间足够,所以只要满足上面的公式,就不会出现垃圾回收期间提升失败的情况;因此,该参数的设置必须与Xmn相关联。-Djava.awt.headless=true这个参数一般用在最后。这个完整参数的作用如下。有时我们在J2EE项目中会用到一些图表工具如:jfreechartforweb网页输出GIF/JPG等流。在winodws环境下,一般我们的app服务器在输出图形的时候不会遇到什么问题,但是在linux/unix环境下,我们经常会遇到异常导致你在winodws开发环境下画图。显示效果不错,但是在linux/unix下无法显示,所以加这个参数可以避免这种情况。上述配置基本可以实现:更快的系统响应时间,更快的JVM回收速度而不影响系统响应速度,最大化JVM内存,最小化线程阻塞,2.3Tomcat容器中的优化。该命令经过优化,增加了系统可用的JVM数量、垃圾收集效率和线程阻塞,提高了系统响应效率。还有一个很重要的指标我们没有优化,就是吞吐量。记得我们第三天学习的时候说过,系统本身可以处理1000个,但是你没有优化配置让它默认只能处理25个。那么我们来看看Tomcat容器中的优化。打开tomcat安装目录下的confserver.xml文件,找到这一行:
