首页 > 系统相关 >Tomcat调优总结(Tomcat自身优化、Linux内核优化、JVM优化)【转】

Tomcat调优总结(Tomcat自身优化、Linux内核优化、JVM优化)【转】

时间:2024-04-25 14:45:14浏览次数:26  
标签:Tomcat tomcat 队列 调优 线程 acceptCount net 优化

Tomcat自身的调优是针对conf/server.xml中的几个参数的调优设置。首先是对这几个参数的含义要有深刻而清楚的理解。以tomcat8.5为例,讲解参数。

同时也得认识到一点,tomcat调优也受制于linux内核。linux内核对tcp连接也有几个参数可以调优。

因此我们可以将tomcat调优分为linux内核优化、java虚拟机调优和tomcat自身的优化。

 

 一、Tomcat自身优化

1. maxThreads :tomcat创建的最大线程数,也就是同时处理的请求最大并发数。默认值是200

官网:The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool. Note that if an executor is configured any value set for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1 to make clear that it is not used.

 maxThreads如何配置(转)

一般的服务器操作都包括量方面:1计算(主要消耗cpu),2等待(io、数据库等)

第一种极端情况,如果我们的操作是纯粹的计算,那么系统响应时间的主要限制就是cpu的运算能力,此时maxThreads应该尽量设的小,降低同一时间内争抢cpu的线程个数,可以提高计算效率,提高系统的整体处理能力。

第二种极端情况,如果我们的操作纯粹是IO或者数据库,那么响应时间的主要限制就变为等待外部资源,此时maxThreads应该尽量设的大,这样才能提高同时处理请求的个数,从而提高系统整体的处理能力。此情况下因为tomcat同时处理的请求量会比较大,所以需要关注一下tomcat的虚拟机内存设置和linux的open file限制。

我在测试时遇到一个问题,maxThreads我设置的比较大比如3000,当服务的线程数大到一定程度时,一般是2000出头,单次请求的响应时间就会急剧的增加,

百思不得其解这是为什么,四处寻求答案无果,最后我总结的原因可能是cpu在线程切换时消耗的时间随着线程数量的增加越来越大,

cpu把大多数时间都用来在这2000多个线程直接切换上了,当然cpu就没有时间来处理我们的程序了。

以前一直简单的认为多线程=高效率。。其实多线程本身并不能提高cpu效率,线程过多反而会降低cpu效率。

当cpu核心数<线程数时,cpu就需要在多个线程直接来回切换,以保证每个线程都会获得cpu时间,即通常我们说的并发执行。

所以maxThreads的配置绝对不是越大越好。

现实应用中,我们的操作都会包含以上两种类型(计算、等待),所以maxThreads的配置并没有一个最优值,一定要根据具体情况来配置。

最好的做法是:在不断测试的基础上,不断调整、优化,才能得到最合理的配置。

2. acceptCount:当tomcat的线程数达到了最大时,接收排队的最大请求个数。默认值为100

官网:the maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.

 

maxThreads与acceptCount这两个值是如何起作用的呢?

 

情况1:接受一个请求,此时tomcat起动的线程数没有到达maxThreads,tomcat会起动一个线程来处理此请求。

 

情况2:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,tomcat会把此请求放入等待队列,等待空闲线程。

 

情况3:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,等待队列中的请求个数也达到了acceptCount,此时tomcat会直接拒绝此次请求,返回connection refused。

对于第3种情况,在看过一篇分析connection timeout问题产生的原因后,等待队列的请求个数这个值可能是由acceptCount参数决定,也有可能由linux内核参数net.core.somaxconn决定。

 

 

关联:我在网上看来一篇文章写分析linux上TCP connection timeout的原因,这篇文章中提到一个内核参数 net.core.somaxconn。

我就想tomcat的acceptCount与net.core.somaxconn到底是什么关系呢。 

我做了一个实验,

1. 我将tomcat的acceptCount设置为3000 ,net.core.somaxconn设置为8192

那么我用ss -lt 指令查看在tomcat起的端口上的send_q值是3000  可见这是acceptCount的值。

2.我将tomcat的acceptCount设置为10000,net.core.somaxconn设置为8192

同样用ss -lt指令查看在tomcat起的端口上的send_q值是8192,可见这是somaxconn的值。

 所以,我总结的是,acceptCount设置的值要一般小于net.core.somaxconn这个参数,这样acceptCount的值才会起作用。net.core.somaxconn 这个参数默认值是128 ,所以需要改这个参数值。后面再介绍改这个值的方法。

 

acceptCount如何配置?(转)

我一般是设置的跟maxThreads一样大,这个值应该是主要根据应用的访问峰值与平均值来权衡配置的。

如果设的较小,可以保证接受的请求较快相应,但是超出的请求可能就直接被拒绝

如果设的较大,可能就会出现大量的请求超时的情况,因为我们系统的处理能力是一定的。

3. maxConnections

官网:

The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will accept, but not process, one further connection. This additional connection be blocked until the number of connections being processed falls below maxConnections at which point the server will start accepting and processing new connections again. Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount setting. The default value varies by connector type. For NIO and NIO2 the default is 10000. For APR/native, the default is 8192.

Note that for APR/native on Windows, the configured value will be reduced to the highest multiple of 1024 that is less than or equal to maxConnections. This is done for performance reasons.
If set to a value of -1, the maxConnections feature is disabled and connections are not counted.

Tomcat允许的同时存在的最大连接数

 acceptCount、maxConnections是tcp层相关的参数。

4.connectionTimeOut :connectionTimeOut=10000是说建立一个socket连接后,如果一直没有收到客户端的FIN,也没有数据过来,那么此连接也必须等到10s后,才能被超时释放,我理解是tomcat就直接释放这个连接。以毫秒为单位,server.xml默认设置是20秒。

官网:The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false, this timeout will also be used when reading the request body (if any).

 

 

修改方法:

  vi server.xml 打开server.xml文件

将 

<!--
 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
 maxThreads="150" minSpareThreads="4"/>
 -->
修改为:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="1500" minSpareThreads="50" prestartminSpareThreads="true"/>

<Connector 
 port="8080" 
 protocol="HTTP/1.1" 
 connectionTimeout="20000" 
 redirectPort="8443" 
 />
修改为

<Connector executor ="tomcatThreadPool" port="8009" protocol="org.apache.coyote.http11.Http11Nio2Protocol" connectionTimeout="20000" maxConnections="10000" redirectPort="8443" acceptCount="1500"/>

下面的图为TCP三次握手与accept交互

 

 

 SYN队列称为半连接队列,由内核参数 net.ipv4.tcp_max_syn_backlog 设置.

Accept队列称为完全连接队列,三次握手已经完成,但还未被应用层接收(accept),但也处于ESTABLISHED状态。队列长度由listen的backlog参数和内核的 net.core.somaxconn 参数共同决定。由listen()函数的第二个参数 backlog 指定,内核硬限制由 net.core.somaxconn 限制,即队列长度实际的值由min(backlog,somaxconn) 来决定

客户端使用connect向服务器发送TCP连接,三次握手就发生了。当1.1步骤 客户端首先发送SYN到达服务端后,内核会把连接信息放到SYN队列中,同时回一个SYN+ACK包给客户端。一段时间后,客户端再次发来ACK包后,内核会把连接从SYN队列中取出,再把这个连接放到ACCEPT队列中。应用服务器调用accept时,其实就是直接从ACCEPT队列中取出已经建立成功的连接套接字。

 

还有一张图是TCP握手建立连接的流程和队列

 

 Tomcat原理概要

Tomcat大致分为两个部分,Connector组件及Container组件。Connector组件负责控制入口连接,并关联着一个Executor。Container负责Servlet容器的实现,Executor负责具体的业务逻辑,如Servlet的执行。一个请求到达服务器后,经过以下关键几步,参见下图:

  1. OS与客户端握手并建立连接,并将建立的连接放入完成队列,不妨叫Acceptor Queque。这个队列的长度就是Connector的acceptCount值。

  2. Tomcat中的acceptor线程,不断从Acceptor Queque中获取连接。

  3. Acceptor Queque队列中没有连接,Acceptor线程继续监视

  4. Acceptor Queque队列中有新连接,Acceptor线程将检查当前的连接数是否超过了maxConnections

  5. 如果超过maxConnections,则阻塞。直到连接数小于maxConnections,acceptor线程将请求交由Executor负责执行。

  6. Executor将分配worker线程来处理请求数据的读取,处理(servlet的执行)以及响应。

    acceptCount

    acceptCount 实际上是Bind Socket时候传递的backlog值,在linux平台下含义是已经建立连接还没有被应用获取的连接队列最大长度。此时,如果请求个数达到了acceptCount,新进的请求将抛出refuse connection.

 

二、Linux内核参数优化

1. linux系统对当前用户的单一进程同时可打开的文件数量的限制

 查看系统允许当前用户进程打开的文件数量的限制: ulimit -u     默认值为1024 。即是Linux操作系统对一个进程打开的文件句柄数量的限制

对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。

修改方法:

 sudo vi /etc/security/limits.conf 

增加如下:

prouser  soft   nofile 65536
prouser  hard nofile 65536

prouser  soft  nproc 65536

prouser hard nproc 65536

修改完后保存此文件。

 

nproc是操作系统级别对每个用户创建的进程数的限制

2.Linux网络内核对TCP连接的有关限制

修改方法:   sudo vi /etc/sysctl.conf   增加如下:   net.ipv4.tcp_tw_reuse = 1 

net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_fin_timeout = 30 
net.ipv4.ip_local_port_range = 10000 65000 
net.ipv4.tcp_max_syn_backlog = 8192 
net.ipv4.tcp_max_tw_buckets = 10000

net.core.somaxconn=8192      accept队列的长度跟这个参数有关

 

sudo /sbin/sysctl -p
  实时生效  

三、JVM调优


JAVA_OPTS="$JAVA_OPTS -server -Xmn2000m -Xms4000m -Xmx4000m -XX:PermSize=128m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=512m -Djuli-logback.configurationFile=file:$CATALINA_HOME/conf/logback.xml"

默认值:

<!--
 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
 maxThreads="150" minSpareThreads="4"/>
 -->

修改为:

<Executor
 name="tomcatThreadPool"
 namePrefix="catalina-exec-"
 maxThreads="500"
 minSpareThreads="30"
 maxIdleTime="60000"
 prestartminSpareThreads = "true"
 maxQueueSize = "100"
/>

参数解释:

maxThreads:最大并发数,默认设置 200,一般建议在 500 ~ 800,根据硬件设施和业务来判断
minSpareThreads:Tomcat 初始化时创建的线程数,默认设置 25
maxIdleTime:如果当前线程大于初始化线程,那空闲线程存活的时间,单位毫秒,默认60000=60秒=1分钟。
prestartminSpareThreads:在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值,如果不等于 true,minSpareThreads 的值就没啥效果了
maxQueueSize:最大的等待队列数,超过则拒绝请求

转自

Tomcat调优总结(Tomcat自身优化、Linux内核优化、JVM优化) - hxwang - 博客园
https://www.cnblogs.com/whx7762/p/9290242.html

标签:Tomcat,tomcat,队列,调优,线程,acceptCount,net,优化
From: https://www.cnblogs.com/paul8339/p/18157676

相关文章

  • 性能问题分析优化实践案例
    星球同学问了这样一个性能分析的问题:他们有一个地图服务,数据都存储在同一个sqlserver实例中,访问量过高导致服务挂了,开发的解决方案是将地图服务的内存从4G升级到8G,问题就解决了。她的问题是开发的这种解决办法是否是最优解,有没有更好的解决方案。由于我对他们的系统架构......
  • Appium控件交互策略:优化自动化测试效率的关键方法
    简介与Web元素操作一样(参考SeleniumWeb元素操作),定位到APP控件元素后,可以对控件进行一系列的操作,实现与APP交互,比如点击、文本输入、元素属性获取等。控件交互常用方法常见操作点击方法element.click()。输入操作element.send_keys('appium')。清除操作element......
  • Oracle "脑残" CBO 优化案例
    今天晚上下班回来才有空看群,群友发了一条很简单的慢SQL问怎么优化。非常简单,我自己模拟的数据。表结构:--auto-generateddefinitionCREATETABLEHHHHHH(IDNUMBERNOTNULLPRIMARYKEY,NAMEVARCHAR2(20),PARAGRAPH_IDNUMBER......
  • 「实用」如何优化自己的码风?
    前言相信不少同学们在前期接触编程时都会为一件事情而发愁,那就是写代码的风格,简称码风,我之前在洛谷上看到过很多题解,码风我都不大满意,所以切水题时需要格式化很长时间的代码,这一篇博客,我们就讲一讲如何优化自已的码风!多用空格有一天,QQ上咱们的业余工作室里有个刚刚编程入门的小......
  • mysql慢sql优化流程
    #查询慢sqlselectdb,time,infofromINFORMATION_SCHEMA.processlistwhereinfoisnotnull;#查看执行计划explainSELECTCOUNT(1)FROMtables_nameWHEREvalid=1;#查看表索引showindexfromtables_name; #查看表数据selectcount(*)fromtables_nam......
  • mysql系列文章---sql优化的7个方面
    1、主键优化主键存储规则:在innoDB引擎中,表数据都是根据主键顺序存放的,主键索引的叶子节点存的是这一行的行数据,非叶子节点只存索引主键设计的原则:a、主键最好顺序生成,否则在插入数据时会产生页分分裂。b、主键不要过长c、不要使用身份证作主键d、业务操作时尽量避免对主键......
  • 前端项目性能优化方案有哪些
    本文分享自天翼云开发者社区《前端项目性能优化方案有哪些》,作者:王****祺一、加载优化(减少http请求数)常用的减少HTTP请求的方法有以下几种:1.合并图片:当页面图片较多时,可以将相似的图片合并为一张大图,从而减少HTTP请求次数。对于不经常变化的图片,使用精灵图或雪碧图进行合并,可......
  • 【介绍一个组件】go: Copy-On-Write map,对读极多和写极少的场景做优化
    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!cnblogs博客zhihuGithub公众号:一本正经的瞎扯代码请看:https://github.com/ahfuzhang/cowmap有这样一种场景:数据量不多的map,在使用中读极多写极少。为了在这种场景下做极致的优化,我实现了copy-on-write的map:其......
  • springboot源码:容器启动过程(扩展业务对象、bean 生命周期)&动态注册自己的业务对象&
    0.SpringbootRun方法启动org.springframework.boot.SpringApplication#run(java.lang.String...)启动 publicConfigurableApplicationContextrun(String...args){ longstartTime=System.nanoTime(); DefaultBootstrapContextbootstrapContext=createBootstrap......
  • 含子查询sql优化案例一例
    0.排查sqlselectEXECSQLEXECTIMERANGE,count(*)fromSQLLOG_OA_2024groupbyEXECSQLEXECTIMERANGEselectexecsqlstr,paramsstr,count(*)from(selectto_char(execsqlstr)execsqlstr,to_char(paramsstr)paramsstr,length(paramsstr)fromSQLLOG_OA_2024where......