Tomcat参数调优:连接数和并发数 连接数实战 并发处理线程数 调整实战
配置项含义默认建议注意备注ConnectionTimeout连接超时20s减少与程序处理能力有关,处理能力越快设置短一点没关系到底多久提示请求超时maxThreads处理连接的最大线程数(并发量)200增加不是越大越好acceptCount(backlog)等待接受accept的请求数量限制100增加socket参数,min(accept,/proc/sys/net/core/somaxconn)超过Tomcat能接收的请求数以后,堆积在操作系统的数量maxConnections最大连接处理数nio 1w apr 8192不变Tomcat能接收的请求限制
请求发到tomcat的顺序:
过程解析:
一个用户请求过来,如果是windows操作系统,它首先进入一个队列,我们的selector会监听底层的事件通知,这个队列就是accept queue,代表TCP的3次握手成功后就会进入到我们的accept queue队列,selector就会收到通知;红线那一部分开始就是Tomcat的范畴了,tomcat就是接受连接(请求),如果请求太多(超过accept+maxConnection),JVM就会崩掉;这1W个请求正在处理里面,这个处理就是我们的线程数量;请求超过默认的1W个请求也就是maxConnection的其他请求就会堆积到操作系统的acceptCount那里。这个参数就是控制堆积数量的,如果是windows系统的话,超过了这个堆积数量,Tomcat的maxConnection塞满了,操作系统的TCP也塞满了,那我们的服务器就不会让它再连接了;但是在Linux下面就不止有acceptCount,握手过程中还有一个SYN队列(acceptCount是指握手完成了才会进入accept queue),我们一般不会去调整红线前的操作系统的东西,因为那是属于内核的。我们一般会去调maxConnection,但是他有1W个,也不怎么会去调了,但什么情况会去调呢?
实战 先用linux服务器来测试
用jMeter发10个请求
配置协议、请求IP、端口、请求方法、接口
然后启动测试
查看结果树,我们可以看每2个请求显示请求成功。虽然我们设置了10个线程,但是只设置了两个连接connections,所以每次只处理了两个请求,其他的都堆积在linux操作系统的默认128中了,所以,我们换windows操作系统试试
换windows操作系统
maxConnection=2
acceptCount=3
windows系统的话一次只能接收5个请求(2个在处理,3个允许在windows操作系统堆积)所以其他5个就会被告知连接失败
打个比方:
有一家理发店(Tomcat),只有两个理发的位置(操作系统2核),假设一个洗剪吹(线程)接待(处理)一个客人(请求)需要30分钟,休息(等待)30分钟;请问这家理发店需要几个洗剪吹才能高效轮班工作。答案肯定是4个。
4=(1+30/30)*2 ——————》(CPU处理至少一个线程+等待时间/处理时间)*2核
假设CPU时间片是50ms,先调度一个线程来执行,执行完50ms的计算后,这个线程需要等待50ms,这时CPU就没事干了,但是他不能停下来,就会再调度一个线程来工作,那么我们一个CPU只需要两个线程就可以把它打满。(2个线程可以处理多个请求,现实中每个请求的处理时间不一致,这就是我们程序代码的质量体现)
4=(1+50/50)*2
6=(1+100/50)*2 (假如每个请求的等待时间很长,我们就可以安排多几个线程来处理)
性能报告:
这个linux是2核的,按照理论公式算出的4个线程的来测试的话:
可以看到这个性能数据不是很满意:响应时间要13秒,错误率30%
将maxThread调回200,起码没有错误率,50个请求每秒吞吐量
将maxThread调到300呢?
这时开始有一些错误请求:因为现在的请求量全部堆积在服务端,这些请求如果20s没有被处理就会请求超时。
所以调高了CPU处理不过来,调低了?CPU没有打满,有些请求没有及时处理也会请求超时。
我们的代码中50ms的等待时间,大概50ms的计算时间,一共响应时间大概是100ms,所以一个请求的程序响应时间本来就慢,吞吐量再怎么调也高不到哪里去,总结就是要提高我们自己的代码质量。
如果说CPU占用率太低的话,可以去调高我们的线程数。
先设置好容量200的线程池
Spring结合servlet的异步处理
有一些应用程序就是很慢,想通过多线程来加速是不可能的,用MQ和CaChe的确可以解决。
负载层+网关层+数据层
因为tomcat更大的作用是基础组件,作用的是我们部署在上面的组件,Nginx是中间件,本身自带很多功能。