Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog

前两天看到一群里在讨论 Tomcat 参数调优 , 看到不止一个人说通过 accept-count 来配置线程池大小 , 我笑了笑 , 看来其实很多人并不太了解我们用的最多的 WebServer Tomcat , 这篇文章就来聊下 Tomcat 调优 , 重点介绍下线程池调优及 TCP 半连接、全连接队列调优 。
Tomcat 线程池先来说下线程池调优 , 就拿 SpringBoot 内置的 Tomcat 来说 , 确实是支持线程池参数配置的 , 但不是 accept-count 参数 , 可以通过 threads.max 和 threads.minSpare 来配置线程池最大线程数和核心线程数 。
如果没有设置 , 则会使用默认值
threads.max: 200threads.minSpare: 10Tomcat 底层用到的 ThreadPoolExecutor 也不是 JUC 原生的线程池 , 而是自定义的 , 做了一些调整来支持 IO 密集型场景使用 , 具体介绍可以看之前写的两篇文章 。
动态线程池(DynamicTp) , 动态调整 Tomcat、Jetty、Undertow 线程池参数篇
以面试官视角万字解读线程池 10 大经典面试题!
通过这两篇文章能了解到 Tomcat 自定义线程池的执行流程及原理 , 然后可以接入动态线程池框架 DynamicTp , 将 Tomcat 线程池交由 DynamicTp 管理 , 使之能享受到动态调参、监控告警的功能 。
在配置中心配置 tomcat 线程池核心参数
spring:dynamic:tp:tomcatTp:corePoolSize: 100maximumPoolSize: 400keepAliveTime: 60Tomcat 线程池调优主要思想就是动态化线程池参数 , 上线前通过压测初步确定一套较优的参数值 , 上线后通过监控、告警实时感知线程池负载情况 , 动态调整参数适应流量的变化 。
线程池调优就说这些吧 , 下面主要介绍下 Tcp backlog 及半连接、全连接队列相关内容 。
划重点

  1. threads.max 和 threads.minSpare 是用来配置 Tomcat 的工作线程池大小的 , 是线程池维度的参数
  2. accept-count 和 max-connections 是 TCP 维度的配置参数
TCP 状态机Client 端和 Server 端基于 TCP 协议进行通信时 , 首先需要经过三次握手建连的 , 通信结束时需要通过四次挥手断连的 。注意所谓的连接其实是个逻辑上的概念 , 并不存在真实连接的 , 那 TCP 是怎么面向连接传输的呢?
TCP 定义了个复杂的有限状态机模型 , 通信双方通过维护一个连接状态 , 来达到看起来像有一条连接的效果 。如下是 TCP 状态机状态流转图 , 这个图非常重要 , 建议大家一定要掌握 。图片来自 TCP 状态机
  1. 图上半部分描述了三次握手建立连接过程中状态的变化
  2. 图下半部分描述了四次挥手断开连接过程中状态的变化

Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog

文章插图
图 2 是通过三次握手建立连接的过程 , 老八股文了 , 建议结合图 1 状态机变化图看 , 图片来源三次握手
Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog

文章插图
图 3 是通过四次挥手断开连接的过程 , 建议结合图 1 状态机变化图看 , 图片来源四次挥手
Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog

文章插图
服务端程序调用 listen() 函数后 , TCP 状态机从 CLOSED 转变为 LISTEN , 并且 linux 内核会创建维护两个队列 。一个是半连接队列(Syn queue) , 另一个是全连接队列(Accept queue) 。

经验总结扩展阅读