tomcat参数以及tcp连接-性能调优实验

本文深入探讨Tomcat服务器性能调优的关键参数,包括TCP队列、连接数、线程池配置及其对高并发场景的影响。通过压测实验,详细分析了如何合理设置这些参数以避免连接等待和超时问题,提升服务响应速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tcp队列和tomcat接受请求相关参数图

该图特别重要!!!
该图特别重要!!!
该图特别重要!!!

它是压测实验的灵魂,流程中经过的参数,将会是性能调优的找瓶颈的关键,那些参数大那些参数小会产生什么问题等就分析这个流程就完了。

PS:网上将tomcat好多比较久远都是用修改tomcat的配置文件,这里我们使用SpringBoot方式的tomcat,所以参数设置也是SpringBoot的参数设置方式。
在这里插入图片描述

tomcat服务器启动:【后边有源码可以看到】
1)TOMCAT创建ServerSocket绑定端口同时设置backlog即tcp的全连接队列大小,告知操作系统tcp半连接队列大小,操作系统默认值为128和tocmat设置的值取最小值!!!因此当tomcat要设置大于128的时候需要修改操作系统的tcp全连接队列的默认值
2)Tomcat 创建处理请求的线程池、Acceptor线程、Poller线程

tomcat服务器接收请求:外部客户端(浏览器、app、Jmeter)发送请求到服务端过程
1)Socket发送第一握手会被放入到tcp半连接队列【SYN_SENT】
2)Socket发送tcptcp三次握手成功操作系统将其从半连接队列转移到全连接队列【ESTABLISHED】
3) Acceptor线程的run方法在执行:
3.1) tcp全连接队列进入到tomcat,tomcat增加一个连接数(AQS方式增加)
3.2) serverSocket#accept之后放入到event队列
4)Poller线程的run方法在执行:
从3)步骤Acceptor线程放入的event的队列消费event,提交给线程池,交给Servlet处理

重要参数含义

连接数:指的是TCP连接数

TCP连接数=操作系统的TCP全连接数+Tomcat的maxConnection
后续会在压测我们用一些工具组合看到ESTABLISHED、SYN_SENT、connectionCount以及currentThreadsBusy的证明

jmeter的http请求的connect超时时间:跟服务器TCP三次握手成功后进入全连接队列需要的时间

可以通过增大jmeter的请求线程数量,减少tomcat的连接数和操作系统的全连接队列查看半连接状态和全连接状态,过了超时时间之后全连接状态全无,同时jmeter报错

acceptCount: ServerSocket设置传递给操作系统的tcp的全连接队列大小

tomcat启动阶段创建ServerSocketChannel时设置tomcat源码的如下:
ServerSocketChannel#bind(addr,backlog) backlog就是acceptCount。

上面的说明的流程中隐含着一些设定会导致的一些后果:

实验步骤

压测实验准备

实验工具

  • 会使用jmeter压测,设置连接超时时间、响应超时时间
  • tcp连接住状态查看 netstat -nat | grep 端口号
  • 使用JMX的MBean,tomcat参数可以通过jconsole等工具的MBean查看
  • 需要懂tomcat源码,java的AQS、tcp、nio

TCP知识补充

TCP状态机
在这里插入图片描述
TCP三次握手四次挥手
在这里插入图片描述

TCP三次握手时候的两个队列
在这里插入图片描述

Client: 发送 SYN,连接状态进入 SYN_SENT
Server: 收到 SYN, 创建连接状态为 SYN_RCVD/SYN_RECV 的 Socket,响应 SYN/ACK
Client: 收到 SYN/ACK,连接状态从 SYN_SENT 变为 ESTABLISHED,响应 ACK
Server: 收到 ACK,连接状态变为 ESTABLISHED
此时,双方的 Socket 都已经进入了 ESTABLISHED 状态,接下来就可以开始交换数据了。
从上面的过程中我们可以看出,Server 需要两个队列,分别存储 SYN_RCVD 状态的连接和 ESTABLISHED 状态的连接,这就是半连接队列和全连接队列。

实验参数设置

  • TCP全连接队列mac和linux下全连接队列默认都是 128

    • 查看:sudo sysctl -a|grep somaxconn
    • mac设置:sudo sysctl -w kern.ipc.somaxconn=2
    • linux设置:sudo sysctl -w net.core.somaxconn=2
  • 创建一个SpringBoot应用 workbench

    • 构造一个请求耗时方法
    @Slf4j
    @RestController
    @RequestMapping("/test")
    public class TestController {
    
      /**
       * @description 方法耗时工具方法,如下功能:
       *  1)制定任务耗时
       *  2)耗时比较大,可以hold住线程  让tomcat线程打满
       * @author yzMa
       * @date 2019/11/5
       * @param  
       * @return  
       */
      @GetMapping("/task/{cost}")
      public String taskCost(@PathVariable long cost) throws InterruptedException {
    
          Thread.sleep(cost);
          
          return "taskCost-"+cost;
      }
    }
    
    
  • tomcat设置

    • server.tomcat.max-threads: 4
    • server.tomcat.max-connections: 5
    • server.tomcat.accept-count: 3
  • tomcat启动脚本

    • nohup java -jar -Dcom.sun.management.jmxremote=true -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.port=7878 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false workbench-0.0.1-SNAPSHOT.jar &
  • jmeter设置

    • 15个线程1秒发送完
    • 在这里插入图片描述
    • http请求设置
      在这里插入图片描述
    • /test/task/60000表示在服务端sleep1分钟(可以看下上面方法的逻辑)目的为了执行时间长一些hold住线程,方便我们用工具查看各个参数的运行时的值。

小工具

nc -4 localhost 7777

ss -tln
Recv-Q 表示全连接队列当前的长度,Send-Q 表示全连接队列配置的长度

压测实验证明

再统计说明下实验参数:

jmeter设置连接超时【tcp的全连接】时间为10秒钟
mac设置的tcp全连接数为2
tomcat设置的acceptCount为3,所以取最小值,所以就是tcp的全连接队列就是2
tomcat设置的全连接数为5
tomcat的线程数为4个
Controller耗时60000ms即1分钟

点击压测按钮,jmeter提交请求。

jconsole查看

4个tomcat线程全部都在忙(Worker的属性exclusiveThread!=null)
在这里插入图片描述

所有的tomcat线程数4个全被hold住60000ms即1分钟,
tomcat的mbean应该看到所有的连接数为5

在这里插入图片描述
如上有5个tomcat的maxConnection全都被使用,4个线程全在忙。

此时在看操作系统的TCP连接状态,15个jmeter线程,5个成功建立TCP全连>接并进入到占用了tomcat的连接,再加上TCP全连接队列是2,总共有【5+2=7】7个全>连接(ESTABLISED)所以剩下的【15-7=8】8个半连接不会进入到全连接队列,而是在半连接队列。

  • netstat -nat |grep 端口号 查看链接状态
    在这里插入图片描述
    完全符合上面的结论。

这里解释下为什么要ESTABLISED个数要除以2,这是因为我本地,部署着服务Server,同时又是我本地访问client。

如下是截图是证明:

  • 我自己访问我自己一次 会看到两个ESTABLISED
  • 其它人访问我一次只会看到一个ESTABLISED
    在这里插入图片描述

那么在此经过jmeter设置的连接超时时间10000ms即10s之后再看

jconsole看到的连接数和线程正在忙的数量跟上面一样不在贴图了。
在这里插入图片描述
原来的8个半连接超时了,全都没有了,同时jmeter报错了
在这里插入图片描述
错误信息:

org.apache.http.conn.ConnectTimeoutException: Connect to localhost:7777 timed out

5个tomcat连接maxConnection,被4个tomcat线程执行【其中一个一定是在>等待,再加上还有连个tcp队列里边的连接还没有进入tomcat,所以此时总共有三个连接在等待,可以得出结论,tomcat连接数和tcp全连接队列越大,线程数越少的情况下, >会有请求一直等待,造成用户得不到响应,直到成客户端超时】

再往过50s之后即1分钟后
在这里插入图片描述

其它请求一次类推,一次最多进入处理4个,有一个等待或者没有等待【取决于在当前的连接数是否】。

小结:

tomcat核心参数:
server:
tomcat:
max-threads: 4
max-connections: 5
accept-count: 3

TCP的半连接队列【未完成三次握手进入的队列】
TCP的全连接队列【三次握手完成从半连接队列转移到的队列】

查看操作系统的全连接队列: sudo sysctl -a |grep somaxconn 默认都是128
mac设置:sudo sysctl -w kern.ipc.somaxconn=2
linxu设置:sudo sysctl -w net.core.somaxconn=2

tomcat的acceptCount 是ServerScoket#bind(arrd,backlog) 是告知操作系统tcp全连接的队列长度,操作系统默认为128,默认值和tomcat传递值取小值。所以当tomcat设置大于128的时候需要设置操作系统的值。

maxConnection连接数+tcp全连接队列(三次握手全结束)=tcp全连接的总数

这个值如果大于tomcat核心线程数就在高并发下(所有线程全都在执行任务)会出现等待,线程处理越慢,剩下多余的tcp连接等待时间就越长。

jmeter的连接超时时间就是 建立tcp全连接的时候等待时间,如果tomcat的maxConnection的指标较小或者jmeter的请求线程比较多,

即:jmeter的线程数-tcp全连接队列-tomcat最大连接数>0,大于0的jmeter线程就会出现半连接
如果maxConnection+min(acceptCount,tcp全连接队列大小) - tomcat线程数>0 会有TCP全连接等待问题,
如果tomcat处理比较慢,tcp半连接的线程会超时 从半连接队列移除 jmeter失败

以往看书,帖子都是很理性,这样有实验数据就变得很感性。
看得见摸得着的东西,记忆才会深刻。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值