Tomcat调优参数

tomcat的整体结构:

tomcat主要有两个核心的功能:

1.处理socket连接,字节流的request responese转换
2.加载管理servlet

所以 tomcat设计了两个组件:
connector和container
在这里插入图片描述
在这里插入图片描述
容器在xml中是这样呈现的
在这里插入图片描述

tomcat的启动流程

我们纵向观察一下启动流程
在这里插入图片描述

回到正题

默认的tomcat配置主要有:

server.tomcat.accept-count:等待队列长度,默认100
server.tomcat.max-connections:最大可被连接数 默认10000
server.tomcat.max-threads:最大工作线程数 默认200
server.tomcat.min-threads:最小工作线程数 默认10

首先来看线程数:

maxThreads、minSpareThreads是tomcat工作线程池的配置参数。
maxThreads就相当于jdk线程池的maxPoolSize,而minSpareThreads就相当于jdk线程池的corePoolSize。

为什么呢?

tomcat连接器(connector)处理socket相关请求后会放入到线程池中。
tomcat扩展了java原生的线程池。TreadpoolExecutor

回顾一下ThreadpoolExecutor:

public ThreadPoolExecutor(int corePoolSize, //核心线程数
                          int maximumPoolSize, //最大线程数
                          long keepAliveTime, //存活时间
                          TimeUnit unit, //存活时间单位
                          BlockingQueue<Runnable> workQueue, //阻塞队列
                          ThreadFactory threadFactory, //扩展原生的线程工厂,比如给创建出来的线程取个有意义的名字
                          RejectedExecutionHandler handler)//拒绝策略

每次创建任务,没有达到corePoolSize,线程就创建新线程。达到了核心线程数,新建的线程就会放入到workqueue队列中。线程池中的线程通过poll来努力的从队列中拉活干。

如果线程创建的过多,如果workQueue是有界队列,就会创建临时线程救场,到达了最大线程数maximumPoolSize,就不能创建了。转而进行拒绝策略 handler。比如抛出异常。

如果高峰期过去了,线程池使用 poll(keepAliveTime, unit)来拉活,poll 方法设置了超时时间,如果超时了仍然两手空空没拉到活,表明它太闲了,这个线程会被销毁回收。

tomcat中的线程池是定制版的,定制了任务队列和线程工厂

// 定制版的任务队列
taskqueue = new TaskQueue(maxQueueSize);
 
// 定制版的线程工厂
TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());
 
// 定制版的线程池
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf);

tomcat和原生的有什么不同呢?

tomcat的线程池主要在于总线程数达到 maximumPoolSize,则继续尝试把任务添加到任务队列中去。
如果缓冲队列也满了,插入失败,执行拒绝策略。
而原生的是线程数达到maximumPoolSize,就执行拒绝策略。

tomcat也就是重写了execute

public void execute(Runnable command, long timeout, TimeUnit unit) {
      submittedCount.incrementAndGet();
      try {
          // 调用 Java 原生线程池的 execute 去执行任务
          super.execute(command);
      } catch (RejectedExecutionException rx) {
         // 如果总线程数达到 maximumPoolSize,Java 原生线程池执行拒绝策略
          if (super.getQueue() instanceof TaskQueue) {
              final TaskQueue queue = (TaskQueue)super.getQueue();
              try {
                  // 继续尝试把任务放到任务队列中去
                  if (!queue.force(command, timeout, unit)) {
                      submittedCount.decrementAndGet();
                      // 如果缓冲队列也满了,插入失败,执行拒绝策略。
                      throw new RejectedExecutionException("...");
                  }
              } 
          }
      }

同时 Tomcat 还实现了定制版的任务队列,重写了 offer 方法,使得在任务队列长度无限制的情况下,线程池仍然有机会创建新的线程.

public class TaskQueue extends LinkedBlockingQueue<Runnable> {
 
  ...
   @Override
  // 线程池调用任务队列的方法时,当前线程数肯定已经大于核心线程数了
  public boolean offer(Runnable o) {
 
      // 如果线程数已经到了最大值,不能创建新线程了,只能把任务添加到任务队列。
      if (parent.getPoolSize() == parent.getMaximumPoolSize()) 
          return super.offer(o);
          
      // 执行到这里,表明当前线程数大于核心线程数,并且小于最大线程数。
      // 表明是可以创建新线程的,那到底要不要创建呢?分两种情况:
      
      //1. 如果已提交的任务数小于当前线程数,表示还有空闲线程,无需创建新线程
      if (parent.getSubmittedCount()<=(parent.getPoolSize())) 
          return super.offer(o);
          
      //2. 如果已提交的任务数大于当前线程数,线程不够用了,返回 false 去创建新线程
      if (parent.getPoolSize()<parent.getMaximumPoolSize()) 
          return false;
          
      // 默认情况下总是把任务添加到任务队列
      return super.offer(o);
  }
  
}

接着看剩下的两个参数:

acceptCount 用来控制内核的 TCP 连接队列长度。
maxConnections 用于控制 Tomcat 层面的最大连接数。

回顾下 TCP 连接的建立过程:客户端向服务端发送 SYN 包,服务端回复 SYN+ACK,同时将这个处于 SYN_RECV 状态的连接保存到半连接队列。客户端返回 ACK 包完成三次握手,服务端将 ESTABLISHED 状态的连接移入accept 队列,等待应用程序(Tomcat)调用 accept 方法将连接取走。

Tomcat 中的maxConnections是指 Tomcat 在任意时刻接收和处理的最大连接数。当 Tomcat 接收的连接数达到 maxConnections 时,Acceptor 线程不会再从 accept 队列中取走连接,这时 accept 队列中的连接会越积越多。

maxConnections 的默认值与连接器类型有关:NIO 的默认值是 10000,APR 默认是 8192。

备注:APR(Apache Portable Runtime Libraries)是 Apache 可移植运行时库,它是用 C 语言实现的,其目的是向上层应用程序提供一个跨平台的操作系统接口库。Tomcat 可以用它来处理包括文件和网络 I/O,从而提升性能。Tomcat 支持的连接器有 NIO、NIO.2 和 APR。

Tomcat 的最大并发连接数等于maxConnections + acceptCount。如果 acceptCount 设置得过大,请求等待时间会比较长;如果 acceptCount 设置过小,高并发情况下,客户端会立即触发 Connection reset 异常。

总结

tomcat yml配置

server:
  tomcat:
    uri-encoding: UTF-8
    #最大工作线程数,默认200, 4核8g内存,线程数经验值800
    #线程数的经验值为:1核2g内存为200,线程数经验值200;4核8g内存,线程数经验值800
    #操作系统做线程之间的切换调度是有系统开销的,所以不是越多越好。
    max-threads: 800
    # 等待队列长度,默认100
    accept-count: 1000
    max-connections: 
    # 最小工作空闲线程数,默认10, 适当增大一些,以便应对突然增长的访问量
   min-spare-threads: 100

附:命令行查看 Tomcat 指标

1找到进程

ps -ef | grep tomcat

2接着查看进程状态的大致信息,通过cat/proc//status

3 监控进程的 CPU 和内存资源使用情况:

先top命令 定位最大cpu最大的是哪个进程

更精细化的 top 命令查看这个 Java 进程中各线程使用 CPU

top -H -p pid # 显示某个进程所有活跃的线程消耗情况。

在这里插入图片描述

4.查看 Tomcat 的网络连接

netsstat -na | grep 8080

\5. 通过 ifstat 来查看网络流量

发布了93 篇原创文章 · 获赞 26 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/sxj159753/article/details/104967352
今日推荐