tomcat性能调优总结

多篇文章总结而来(自己未测试过,如果有问题请指教):

调整Tomcat的并发线程数到5000+
 
1. 调整server.xml的配置
 
先调整maxThreads的数值,在未调整任何参数之前,默认的并发线程可以达到40。
 
调整此项后可以达到1800左右。

<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"
maxThreads="32000"
/>

再试试使用非阻塞的库。

<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"
maxThreads="32000"
protocol="org.apache.coyote.http11.Http11NioProtocol" 
/>

结果和不使用非阻塞的库差不多。

线程数在2000左右。

2.调整用户打开的文件数限制

ulimit -n 32768

调整后,线程数增加到了5900左右。

3.减少缓冲区大小到1024

...
maxThreads="32000"  
socket.appReadBufSize="1024"  
socket.appWriteBufSize="1024"  
bufferSize="1024"
...

无效果

综合来看,还是达不到10000并发。下次增加内存再试试。

当前的内存配置是1024M。

另外,在server.xml中的参数acceptCount ,保存的是,当并发请求数超过 maxThreads 时,系统还能存储的请求的队列的长度。默认是100。当队列已经满了的时候,后续的请求将获得一个“connectin refused”的错误。



<--  将tomcat servlet.xml 这句话注释去掉就可以了  --> 
 
< Executor 
     name = "tomcatThreadPool"         <!--线程名称-->
     namePrefix="catalina-exec-" 
     maxThreads="150"                <!--最大处理连接数线程-->
     minSpareThreads="4" />          <!--保留最少线程数-->
     
     
<!-- 将原有的Connector 替换为带有线程池的Connector如下,其实servlet.xml已经有了,只要打开就可以了,将原来的去掉   -->
< Connector 
     executor = "tomcatThreadPool"
     port = "8080" 
     protocol = "HTTP/1.1"
     connectionTimeout = "20000"
     redirectPort = "8443" 
     minProcessors = "5"          <!-- 同时处理请求的最小数 -->
     maxProcessors="75"         <!-- 同时处理请求的最大数 -->
     acceptCount="1000" />      <!-- 接受最大并发数量 ,超过这个数量就会返回连接被拒绝 -->


Tomcat内存溢出分析及解决方法

堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的,本文将详细介绍Tomcat内存溢出,需要了解更多的朋友可以参考下

JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。 

一、内存溢出类型 
1、java.lang.OutOfMemoryError: PermGen space 
JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多。 

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。 
一个最佳的配置例子:(经过本人验证,自从用此配置之后,再未出现过tomcat死掉的情况) 

set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m 
在linux下 在tomcathome/conf/catalina.sh中加上如标红所示的一句代码:可以增加tomcat jvm 的内存,这样就不容易出现内存溢出的现象了! 
# ----- Execute The Requested Command ----------------------------------------- 
JAVA_OPTS="-server -Xms512m -Xmx2048m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m" 
# Bugzilla 37848: only output this if we have a TTY 
2、java.lang.OutOfMemoryError: Javaheap space 
第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。如果内存剩余不到40%,JVM就会增大堆到Xmx设置的值,内存剩余超过70%,JVM就会减小堆到Xms设置的值。所以服务器的Xmx和Xms设置一般应该设置相同避免每次GC后都要调整虚拟机堆的大小。假设物理内存无限大,那么JVM内存的最大值跟操作系统有关,一般32位机是1.5g到3g之间,而64位的就不会有限制了。 

注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。 

垃圾回收GC的角色 
JVM调用GC的频度还是很高的,主要两种情况下进行垃圾回收: 
当应用程序线程空闲;另一个是java内存堆不足时,会不断调用GC,若连续回收都解决不了内存堆不足的问题时,就会报out of memory错误。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。 
根据GC的机制,程序的运行会引起系统运行环境的变化,增加GC的触发机会。 
为了避免这些问题,程序的设计和编写就应避免垃圾对象的内存占用和GC的开销。显示调用System.GC()只能建议JVM需要在内存中对垃圾对象进行回收,但不是必须马上回收, 
一个是并不能解决内存资源耗空的局面,另外也会增加GC的消耗。 

二、JVM内存区域组成 
简单的说java中的堆和栈 
java把内存分两种:一种是栈内存,另一种是堆内存 
1、在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配; 
2、堆内存用来存放由new创建的对象和数组 
在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理 
堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢; 
栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。 

java堆分为三个区:New、Old和Permanent 
GC有两个线程: 
新创建的对象被分配到New区,当该区被填满时会被GC辅助线程移到Old区,当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。Old区的大小等于Xmx减去-Xmn 
java栈存放 
栈调整:参数有+UseDefaultStackSize -Xss256K,表示每个线程可申请256k的栈空间 
每个线程都有他自己的Stack 

三、JVM如何设置虚拟内存 
提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。 
提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。 
提示:JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。 
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。 
提示:假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。 
简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制, 
这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了 

注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。 

提示:设置NewSize、MaxNewSize相等,"new"的大小最好不要大于"old"的一半,原因是old区如果不够大会频繁的触发"主" GC ,大大降低了性能 
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64; 
由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。 
解决方法:手动设置Heap size 
修改TOMCAT_HOME/bin/catalina.bat 
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: 
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m" 

四、性能检查工具使用 
定位内存泄漏: 
JProfiler工具主要用于检查和跟踪系统(限于Java开发的)的性能。JProfiler可以通过时时的监控系统的内存使用情况,随时监视垃圾回收,线程运行状况等手段,从而很好的监视JVM运行情况及其性能。 
1. 应用服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位。

*对象分配规则

1.对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC

2.大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。

3.长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,知道达到阀值对象进入老年区。

4.动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。

5.空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。 

JVM监控工具jstack, jconsole, jinfo, jmap, jdb, jstat

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值