Tomcat优化参考建议 —— 筑梦之路
linux内核参数调优1. 打开文件数ulimit -u 默认值为1024 即Linux操作系统对一个进程打开的文件句柄数量的限制。分为软限制和硬限制软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。nproc 操作系统级别对每个用户创建的进程数的限制。cat /etc/security/limits.conf EOF * soft nofile 655360 * hard nofile 655360 * soft nproc 655360 * hard nproc 655360 EOF2. TCP连接cat /etc/sysctl.conf EOF 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.somaxconn8192 # accept队列的长度跟这个参数有关 EOF sysctl -p --systemJVM参数调优JAVA_OPTS$JAVA_OPTS -server -Xmn2000m -Xms4000m -Xmx4000m -XX:PermSize128m -XX:UseConcMarkSweepGC -XX:MaxPermSize512m -Djuli-logback.configurationFilefile:$CATALINA_HOME/conf/logback.xml tomcat配置文件参数调整 默认值: !-- Executor nametomcatThreadPool namePrefixcatalina-exec- maxThreads150 minSpareThreads4/ -- 修改为: Executor nametomcatThreadPool namePrefixcatalina-exec- maxThreads500 minSpareThreads30 maxIdleTime60000 prestartminSpareThreads true maxQueueSize 100 / 参数解释 maxThreads最大并发数默认设置 200一般建议在 500 ~ 800根据硬件设施和业务来判断 minSpareThreadsTomcat 初始化时创建的线程数默认设置 25 maxIdleTime如果当前线程大于初始化线程那空闲线程存活的时间单位毫秒默认6000060秒1分钟。 prestartminSpareThreads在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值如果不等于 trueminSpareThreads 的值就没啥效果了 maxQueueSize最大的等待队列数超过则拒绝请求tomcat参数调优主要配置文件conf/server.xml1. maxThreadstomcat创建的最大线程数也就是同时处理的请求最大并发数默认值是200。maxThreads如何配置一般的服务器操作都包括量方面计算主要消耗cpu等待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。maxThreads与acceptCount这两个值是如何起作用的呢情况1接受一个请求此时tomcat起动的线程数没有到达maxThreadstomcat会起动一个线程来处理此请求。情况2接受一个请求此时tomcat起动的线程数已经到达maxThreadstomcat会把此请求放入等待队列等待空闲线程。情况3接受一个请求此时tomcat起动的线程数已经到达maxThreads等待队列中的请求个数也达到了acceptCount此时tomcat会直接拒绝此次请求返回connection refused。对于第3种情况等待队列的请求个数这个值可能是由acceptCount参数决定也有可能由linux内核参数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设置为10000net.core.somaxconn设置为8192同样用ss -lt指令查看在tomcat起的端口上的send_q值是8192,可见这是somaxconn的值。所以acceptCount设置的值要一般小于net.core.somaxconn这个参数这样acceptCount的值才会起作用。net.core.somaxconn 这个参数默认值是128 所以需要改这个参数值。acceptCount如何配置一般是设置的跟maxThreads一样大这个值应该是主要根据应用的访问峰值与平均值来权衡配置的。如果设的较小可以保证接受的请求较快相应但是超出的请求可能就直接被拒绝如果设的较大可能就会出现大量的请求超时的情况因为我们系统的处理能力是一定的。3. maxConnectionsTomcat允许的同时存在的最大连接数。服务器在任何给定时间将接受并处理的最大连接数。当达到此数量时服务器将接受但不处理额外的一个连接。这个额外的连接会被阻塞直到正在处理的连接数低于maxConnections此时服务器将开始再次接受并处理新的连接。请注意一旦达到限制操作系统仍然可能根据acceptCount设置接受连接。默认值因连接器类型而异。对于NIO和NIO2默认值为10000。对于APR/native默认值为8192。请注意在Windows上的APR/native配置中所设置的值将会减少到小于或等于maxConnections的最大1024的倍数值。这是出于性能方面的考虑。如果设置为-1的值则禁用maxConnections特性并且不计数连接。注意acceptCount、maxConnections是tcp层相关的参数。4.connectionTimeOutconnectionTimeOut10000是说建立一个socket连接后如果一直没有收到客户端的FIN也没有数据过来那么此连接也必须等到10s后才能被超时释放我理解是tomcat就直接释放这个连接。以毫秒为单位server.xml默认设置是20秒。此连接器在接收到连接后等待请求 URI 行呈现的毫秒数。使用值 -1 表示无即无限超时。默认值为 60000即 60 秒但请注意随 Tomcat 一起提供的标准 server.xml 文件将此值设置为 20000即 20 秒。除非将 disableUploadTimeout 设置为 false否则在读取请求正文如果有时也将使用此超时。修改方法 vi server.xml 打开server.xml文件 将 !-- Executor nametomcatThreadPool namePrefixcatalina-exec- maxThreads150 minSpareThreads4/ -- 修改为 Executor nametomcatThreadPool namePrefixcatalina-exec- maxThreads1500 minSpareThreads50 prestartminSpareThreadstrue/ 将 Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 / 修改为 Connector executor tomcatThreadPool port8009 protocolorg.apache.coyote.http11.Http11Nio2Protocol connectionTimeout20000 maxConnections10000 redirectPort8443 acceptCount1500/扩展延伸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队列中同时回一个SYNACK包给客户端。一段时间后客户端再次发来ACK包后内核会把连接从SYN队列中取出再把这个连接放到ACCEPT队列中。应用服务器调用accept时其实就是直接从ACCEPT队列中取出已经建立成功的连接套接字。TCP握手建立连接的流程和队列tomcat原理Tomcat大致分为两个部分Connector组件及Container组件。Connector组件负责控制入口连接并关联着一个Executor。Container负责Servlet容器的实现Executor负责具体的业务逻辑如Servlet的执行。一个请求到达服务器后经过以下关键几步参见下图OS与客户端握手并建立连接并将建立的连接放入完成队列不妨叫Acceptor Queque。这个队列的长度就是Connector的acceptCount值。Tomcat中的acceptor线程不断从Acceptor Queque中获取连接。Acceptor Queque队列中没有连接Acceptor线程继续监视Acceptor Queque队列中有新连接Acceptor线程将检查当前的连接数是否超过了maxConnections如果超过maxConnections则阻塞。直到连接数小于maxConnectionsacceptor线程将请求交由Executor负责执行。Executor将分配worker线程来处理请求数据的读取处理servlet的执行以及响应。acceptCountacceptCount 实际上是Bind Socket时候传递的backlog值在linux平台下含义是已经建立连接还没有被应用获取的连接队列最大长度。此时如果请求个数达到了acceptCount新进的请求将抛出refuse connection.