Tomcat调优

基本优化

tomcat调优主要从以下三方面着手: 
1. 内存优化 
2. 并发优化 
3. 内核优化  
1. JVM内存优化  内存
内存溢出的处理办法(tomcat内存优化):
Tomcat内存优化主要是对 tomcat 启动参数优化,我们可以在 tomcat 的启动脚本 catalina.sh(在此文件第一行开始添加新的设置即可)中设置 JAVA_OPTS 参数  JAVA_OPTS=”-server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -Djava.awt.headless=true”  
-server  以服务端模式启动,启动速度会稍微慢点,但性能会高很多.;   
-Xms    java虚拟机初始化时的初始堆大小;   
-Xmx   java虚拟机可使用的最大堆大小;    物理内存的1/4——1/2
-XX:PermSize     内存永久保留区域   
-XX:MaxPermSize   内存最大永久保留区域(老生代对象能占用内存的最大值)   
java.awt.headless=true 与图形操作有关,适用于Linux系统 
注:要加“m”说明是MB,否则就是KB,在启动tomcat时会报内存不足。
注:永久保存区: 
        PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。jvm的gc是不会清理PemGen space的,导致内存溢出 

        常见的内存溢出一般会有下面三种情况:         
1.OutOfMemoryError: Java heap space #堆溢出,若不是程序逻辑bug,可能是项目中引用的jar较多导致        
2.OutOfMemoryError: PermGen space #永久保存区域溢出,通常由于加载了过多的类导致        
3.OutOfMemoryError: unable to create new native thread. #当JVM的heap size设置过大时,thread的创建数量便会减少
解决:
1.调整-Xms -Xmx参数可以解决第一种情况  
64位操作系统对堆内存大小无限制 
        堆的大小可以使用 java -Xmx***M  -version 命令来测试,***位置填写想设置的内存大小。支持的话会出现jdk的版本号,不支持会报错。      
        -Xms -Xmx一般配置成一样比较好,比如set JAVA_OPTS= -Xms1024m -Xmx1024m     注意:java -Xmx***M  version 命令来测试的最大堆内存是 -Xmx与 -XX:PermSize的和,比如系统支持最大的jvm堆大小是1.5G,那  -Xmx1024m  -XX:PermSize=768M 是无法运行的     
2.加大-XX:PermSize  -XX:MaxPermSize来解决第二种情况   
3.解决问题3方法如下:   
1).如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。   
2).如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:   
a, MaxProcessMemory 使用64位操作系统   
b, JVMMemory   减少JVMMemory的分配  使用tomcat的catalina.sh这里配置,JAVA_OPTS=-Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m-XX:MaxPermSize=256m   
c, ThreadStackSize  减小单个线程的栈大小  
这个异常问题本质原因是:
我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。 
能创建的线程数的具体计算公式如下: 
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一个进程的最大内存 
JVMMemory        JVM内存 
ReservedOsMemory  保留的操作系统内存 
ThreadStackSize     线程栈的大小  
        在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。
2. 并发优化    配置文件
线程池设置:
线程池指定Web请求负载的数量,因此,为获得更好的性能这部分应小心处理。可以通过调整连接器属性“maxThreads”完成设置。maxThreads的值应该根据流量的大小,如果值过低,将有没有足够的线程来处理所有的请求,请求将进入等待状态,只有当一个的处理线程释放后才被处理;如果设置的太大,Tomcat的启动将花费更多时间。因此它取决于我们给maxThreads设置一个正确的值。 
#vim server.xml 
<Connector port="8080" protocol="HTTP/1.1"
        maxThreads="500"
        connectionTimeout="20000"
        redirectPort="8443" />

 

在上述配置中,maxThreads值设定为“500”,这指定可以由服务器处理的并发请求的最大数量。如果没有指定,这个属性的默认值为“200”。任何多出的并发请求将收到“拒绝连接”的错误提示,直到另一个处理请求进程被释放。错误看起来如下,
[org.apache.tomcat.util.threads.ThreadPool logFull SEVERE: All threads (500) are  currently busy, waiting. Increase maxThreads (500) or check the servlet status    
最好使用“Tomcat集群”的多个实例。也就是说,如果有“1000”请求,两个Tomcat实例设置“maxThreads= 500”,而不在单Tomcat实例的情况下设置maxThreads=1000。  
<Connector port="9027"      
                protocol="HTTP/1.1"     
                maxHttpHeaderSize="8192"     
                maxThreads="1000"     
                minSpareThreads="100"     
                maxSpareThreads="1000"     
                minProcessors="100"     
                maxProcessors="1000"    
                enableLookups="false"     
                URIEncoding="utf-8"     
                acceptCount="1000"     
                redirectPort="8443"     
                disableUploadTimeout="true"/> 

 

参数说明
maxThreads   客户请求最大线程数
minSpareThreads    Tomcat初始化时创建的 socket 线程数
maxSpareThreads   Tomcat连接器的最大空闲 socket 线程数
enableLookups       若设为true, 则支持域名解析,可把 ip 地址解析为主机名
redirectPort        在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口
acceptAccount   监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads  )
connectionTimeout  连接超时
minProcessors         服务器创建时的最小处理线程数
maxProcessors        服务器同时最大处理线程数
URIEncoding    URL统一编码

 

3. 内核优化  系统
Tomcat运行过程中可能会出现大量ESTABLISHED连接与Time_Wait连接
# netstat -tan | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
CLOSE_WAIT 348
ESTABLISHED 1240
TIME_WAIT 5621 监控Apache与tomcat之间的链接端口
#netstat -n | grep 8009 | wc -l
7198

 

1、怎样解决time_wait过多的问题:
通过调整内核参数: 
# vim /etc/sysctl.conf #编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
# /sbin/sysctl -p #让参数生效。 
配置说明:
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1    表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1  表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout=30修改系統默认的 TIMEOUT 时间。
如果以上配置调优后性能还不理想,可继续修改一下配置: 
# vi /etc/sysctl.conf  net.ipv4.tcp_keepalive_time = 1200 #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。 
net.ipv4.ip_local_port_range = 1024 65000 #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。  n
et.ipv4.tcp_max_syn_backlog = 8192 #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。 
net.ipv4.tcp_max_tw_buckets = 5000 #表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。 
默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。 
调优完毕,再压一下看看效果: 
# netstat -tan | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
ESTABLISHED 968
2、怎么解决请求结束后依然存在大量ESTABLISHED没有被释放  初步推断是tomcat服务器回收session时出了问题,这个一般都跟服务器的Timeout设置有联系。 
查看tomcat的配置文件 server.xml
<Connector port="8080" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8443" URIEncoding="UTF-8"/>
*****检查配置得出20000毫秒的时候acceptCount=”100” ,明显不合理,最大连接数也太小了吧。 
所以进一步优化: 
connectionTimeout="20000" 改为 connectionTimeout="100" 
acceptCount="100"改为acceptCount="5000"
posted @ 2020-10-20 23:05  梦里花落知多少sl  阅读(517)  评论(0编辑  收藏  举报