天天看点

【Tomcat】Tomcat参数调优:连接数和并发数

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的顺序:

【Tomcat】Tomcat参数调优:连接数和并发数

连接数

【Tomcat】Tomcat参数调优:连接数和并发数
【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个,也不怎么会去调了,但什么情况会去调呢?

  • 什么时候需要调整connections?如何调整?
    • connections小于maxThread的时候;需要调大;最好是比预期的最高并发数要大20%; 反正是堆积到Tomcat的work处理线程池中(堆积占内存)。
    • 假如我们有5个CPU,我们开了有5个线程在执行处理,但是我们的连接数connection才3个,那么我们就会浪费了2个CPU资源。实际上我们的处理能力还很强,但是我们没有让我们的请求进来了。
    • 假如我们现在做一个程序,并发量是5000的,那我们的connections就不能低于5000,而且还要比5000高个20%。
  • 什么时候需要调整acceptCount?
    • 想要受理更多的用户请求,却又不想堆积到tomcat中,利用操作系统来高效的堆积,可以调整为最高并发数-connections
    • 实际上不需要调整,tomcat默认acceptCount100个,linux默认128;最好是连接控制交给应用程序,这样方便管理。
    • 假如我们在tomcat中把acceptCount改成200,但是操作系统的128没有改,但其实还是128.
      【Tomcat】Tomcat参数调优:连接数和并发数

实战

【Tomcat】Tomcat参数调优:连接数和并发数
  • 先用linux服务器来测试
    【Tomcat】Tomcat参数调优:连接数和并发数
    • 用jMeter发10个请求
      【Tomcat】Tomcat参数调优:连接数和并发数
【Tomcat】Tomcat参数调优:连接数和并发数

配置协议、请求IP、端口、请求方法、接口

【Tomcat】Tomcat参数调优:连接数和并发数
【Tomcat】Tomcat参数调优:连接数和并发数

然后启动测试

【Tomcat】Tomcat参数调优:连接数和并发数

查看结果树,我们可以看每2个请求显示请求成功。虽然我们设置了10个线程,但是只设置了两个连接connections,所以每次只处理了两个请求,其他的都堆积在linux操作系统的默认128中了,所以,我们换windows操作系统试试

【Tomcat】Tomcat参数调优:连接数和并发数

换windows操作系统

【Tomcat】Tomcat参数调优:连接数和并发数
【Tomcat】Tomcat参数调优:连接数和并发数

maxConnection=2

acceptCount=3

windows系统的话一次只能接收5个请求(2个在处理,3个允许在windows操作系统堆积)所以其他5个就会被告知连接失败

【Tomcat】Tomcat参数调优:连接数和并发数

并发处理线程数 调整

  • 线程太少,CPU利用率过低,程序的吞吐量变小,容易堆积
  • 线程太多,上下文频繁切换,性能反而变低。
  • 线程数调成多少合适?
    • 场景代入:服务器配置2核,不考虑内存问题。收到请求,java代码执行耗时50ms,等待数据返回50ms
    • 理想的线程数量=(1 + 代码阻塞时间/代码执行时间 ) * CPU数量
    • 因为我们无法精确时间
    • 实际情况是跑起代码后,压测环境进行调试。不断调整线程数,将CPU达到80%到90%的利用率。
【Tomcat】Tomcat参数调优:连接数和并发数

打个比方:

有一家理发店(Tomcat),只有两个理发的位置(操作系统2核),假设一个洗剪吹(线程)接待(处理)一个客人(请求)需要30分钟,休息(等待)30分钟;请问这家理发店需要几个洗剪吹才能高效轮班工作。答案肯定是4个。

4=(1+30/30)*2 ——————》(CPU处理至少一个线程+等待时间/处理时间)*2核

【Tomcat】Tomcat参数调优:连接数和并发数

假设CPU时间片是50ms,先调度一个线程来执行,执行完50ms的计算后,这个线程需要等待50ms,这时CPU就没事干了,但是他不能停下来,就会再调度一个线程来工作,那么我们一个CPU只需要两个线程就可以把它打满。(2个线程可以处理多个请求,现实中每个请求的处理时间不一致,这就是我们程序代码的质量体现)

4=(1+50/50)*2

6=(1+100/50)*2 (假如每个请求的等待时间很长,我们就可以安排多几个线程来处理)

【Tomcat】Tomcat参数调优:连接数和并发数

实战

【Tomcat】Tomcat参数调优:连接数和并发数
  • 1秒发送1000次,循环10次,也就是10秒发10*1000=1W个请求
    【Tomcat】Tomcat参数调优:连接数和并发数
    【Tomcat】Tomcat参数调优:连接数和并发数
    性能报告:
    【Tomcat】Tomcat参数调优:连接数和并发数
    这个linux是2核的,按照理论公式算出的4个线程的来测试的话:
    【Tomcat】Tomcat参数调优:连接数和并发数
    可以看到这个性能数据不是很满意:响应时间要13秒,错误率30%
    【Tomcat】Tomcat参数调优:连接数和并发数
    将maxThread调回200,起码没有错误率,50个请求每秒吞吐量
    【Tomcat】Tomcat参数调优:连接数和并发数

    将maxThread调到300呢?

    这时开始有一些错误请求:因为现在的请求量全部堆积在服务端,这些请求如果20s没有被处理就会请求超时。

    所以调高了CPU处理不过来,调低了?CPU没有打满,有些请求没有及时处理也会请求超时。

    【Tomcat】Tomcat参数调优:连接数和并发数

    我们的代码中50ms的等待时间,大概50ms的计算时间,一共响应时间大概是100ms,所以一个请求的程序响应时间本来就慢,吞吐量再怎么调也高不到哪里去,总结就是要提高我们自己的代码质量。

    如果说CPU占用率太低的话,可以去调高我们的线程数。

先设置好容量200的线程池

【Tomcat】Tomcat参数调优:连接数和并发数

Spring结合servlet的异步处理

【Tomcat】Tomcat参数调优:连接数和并发数

有一些应用程序就是很慢,想通过多线程来加速是不可能的,用MQ和CaChe的确可以解决。

【Tomcat】Tomcat参数调优:连接数和并发数
【Tomcat】Tomcat参数调优:连接数和并发数

负载层+网关层+数据层

因为tomcat更大的作用是基础组件,作用的是我们部署在上面的组件,Nginx是中间件,本身自带很多功能。