一次tomcat压测调优记录

  

1。前言

该tomcat web应用承担集团登录注册页面功能,对性能有一定要求,由于先前没有太多相关经验(只压测过一个达博服务),这次调得比较艰辛,便做个记录。

2。调优过程

起初没有给运维任何tomcat配置要求,同时也没留意去确认tomcat配置,这个导致了后续压测过程各种诡异的问题。

。在压测初期,持续请求10分钟左右出现无请求进来,netstat查看的tomcat所在服务器存在大量CLOSE_WAIT的连接只
CLOSE_WAIT的连接一般是自己程序中缺少关闭连接等引起,但是查看程序也没发现哪里没有关闭,而且大多CLOSE_WAIT是与浏览器端的http协议下的tcp连接。后经运维排查是centos自身的错误引起,升级到centos -释放- 6 - 6. - el6.centos.12.2。x86_64后解决。

其中对于CLOSE_WAIT和TIME_WAIT的TCP连接起初一直不太理解是怎么出现,怎么解决,后详细查看TCP四次挥手断开连接了解了整个过程。(图片来自网络)
一次tomcat压测调优记录”>,<br/>比如客户端应用程序发起密切的信息,服务端接收到后进入CLOSE_WAIT状态并做ACK,之后服务端程序发起密切的信息,客户端接收到之后进入TIME_WAIT,服务端收到客户端的ACK之后进入封闭状态,客户端TIME_WAIT需要等待到超时才进入封闭状态。</p> <p>基于此,服务器端出现大量CLOSE_WAIT不是一个正常的状态,首先需要确认CLOSE_WAIT状态对方的IP,再查看这个IP对应的代码是否缺少关闭连接只<br/>但是如果出现大量TIME_WAIT,不是太要的紧,只要不占满句柄就行,如果真的占满了可以尝试修改内核TCP超时时间和TCP的重TIME_WAIT用。</p> <p> b。然后压测500个并发出现连接超时和读取超时,这种情况基本是在请求数超过了配置的最大值,一开始找运维排除nginx和vm的限流,然后再查看tomcat的限制,发现tomcat未配置最大线程数,默认情况最大线程数是200年最大等待队100年列,然后修改tomcat的服务器。xml配置</p> <pre类= & lt; Connector 港口=" 8080 ",协议=皁rg.apache.coyote.http11.Http11NioProtocol”, connectionTimeout=" 30000 "   ,,,,,,,enableLookups=癴alse”, maxThreads=" 2048 ", minSpareThreads=" 100 ", acceptCount=" 512 ", URIEncoding=皍tf - 8”/祝辞12

调整协议使用nio的,调整最大线程(maxThreads)为2048用于压测,最小空闲线程数(minSpareThreads) 100年,接收请求队列最大(acceptCount)为512,
,到这里压1000年或2000年者并发都不会出现拒绝请求的情况。

这里再细化下连接超时和读取超时,连接超时处于连接还没建立就超时的状态,如果不是网络问题,多半是maxThreads + acceptCount不够处理并发请求,可以尝试增加这两个值,读取超时是建立连接后,一种是等待在队列太久没处理导致超时,一种是程序自身执行时间太久,可通过访问日志记录请求执行时长排查。

c。再压一段时间后,出现请求响应慢,请求进不来,此时大多是连接拒绝(由于先前调整的线程池,一直还在排查线程池问题),后来查看gc日志发现一直在做完整gc并且老年代内存无法释放,由于没有指定过gc方式,当时以为是gc引起,所以先调整了gc配置为cms 
记录gc日志和服务挂掉时转储内存配置

- xx: + HeapDumpOnOutOfMemoryError  - xx: HeapDumpPath=/卷/logs/heap.bin  - xx: + PrintGCDetails  - xx: + PrintGCTimeStamps  -Xloggc:/卷/日志/gc。log1

修改为cms的gc方式的配置

- xx: + UseConcMarkSweepGC  - xx: + UseParNewGC  - xx: + UseCMSCompactAtFullCollection  - xx: CMSFullGCsBeforeCompaction=10, - xx: + CMSClassUnloadingEnabled  - xx: + CMSParallelRemarkEnabled  - xx: MaxTenuringThreshold=15, - xx: CMSInitiatingOccupancyFraction=70, 1

对cms的gc理解不深,大致知道默认的gc方式是阻塞应用,cms采用并发标记清理的方式,后续再翻书学习下.TODO

d。通过修改gc方式得到了一定的缓解,在压测不到30分钟左右时发现又出现吞吐量降低,响应非常慢的问题,,
大致知道是有很多对象没释放,通过jmap查看前20个占用最大的对象(。/jmap histo pid |头20 - n),好像都还好,最大的是会话不过也才300多米(估计是当时刚好不在压力期间已经被释放完了),,
然后在出现慢的时候倾倒了全部内存下来,但是实在太大了(5克),下载太久,,
之后把堆内存调整为1 g并压到出现慢,查也看转储是会话最大,占百分之八十左右,这时候还没意识到是会话的问题,以为1 g太小看不出根本问题,,
再把堆内存调整为2 g并压到出现慢,查看转储发现会话占了1.5 g,突然灵光一闪,我这边请求会话是封装放到复述的,本地的tomcat会话占这么大是不对的…(闪得也太迟了点吧),然后把tomcat的会话超时时间设置成一分钟果然不会再出现频繁完整GC的问题。再查看代码,原来是封装的会话的地方脑抽的写了个super.getSession(真正)。默认配置下每次请求来都会生成新的会话,并且超时时间是30分钟,在内存中占30分钟才被销毁! !

一次tomcat压测调优记录