tomcat与JVM性能调优

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hemk340200600/article/details/79183633

tomcat的性能调优是实际生产中很重要的一部分,虽然我们平时在调试时只要能跑起来就行,但是实际部署之后,当访问的用户量一增加,就涉及到tomcat的最大并发量等问题。那么如何设置tomcat以及JVM,使我们的web应用的并发量增加呢?


一、tomcat内存优化(Windows 下的catalina.bat;Linux 下的catalina.sh)

先来了解一下一些跟JVM底层相关的一些概念。

运行时存储区:

  • 程序计数器:线程私有。当前线程所执行的字节码的行号指示器。如果线程正在执行一个java方法,记录的是正在执行的虚拟机字节码指令的地址。如果是native方法,计数器的值为空。
  • 虚拟机栈:线程私有。为java方法服务。每个方法在执行时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
  • 本地方法栈:与虚拟机栈类似,不过它是为Naïve方法服务。Java通过Java本地接口JNI(Java Native Interface)来调用其它语言编写的程序,在Java里面用native修饰符来描述一个方法是本地方法。
  • java堆:所有线程共享。即GC堆,堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
  • 方法区:所有线程共享。存储已被虚拟机加载的类信息,常量,运行时常量池、字段信息、方法信息、静态变量、到类classloader的引用、到类class的引用,即时编译器编译后的代码等数据。(方法区又称为永久代)。运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

Java 的内存模型

  • Young,年轻代(易被 GC)。Young 区被划分为三部分,Eden 区和两个大小严格相同的Survivor 区,其中 Survivor 区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用,在 Young区间变满的时候,minor GC 就会将存活的对象移到空闲的Survivor 区间中,根据 JVM 的策略,在经过几次垃圾收集后,仍然存活于Survivor 的对象将被移动到 Tenured 区间。
  • Tenured,终身代/老年代。Tenured 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在 Young 复制转移一定的次数以后,对象就会被转移到 Tenured 区,一般如果系统中用了 application 级别的缓存,缓存中的对象往往会被转移到这一区间。
  • Perm,永久代。主要保存class,method,filed对象,这部门的空间一般不会溢出,除非一次性加载了很多的类,不过在涉及到热部署的应用服务器的时候,有时候会遇到java.lang.OutOfMemoryError : PermGen space的错误,造成这个错误的很大原因就有可能是每次都重新部署,但是重新部署后,类的 class 没有被卸载掉,这样就造成了大量的 class对象保存在了 perm 中,这种情况下,一般重新启动应用服务器可以解决问题。

内存模型与运行时存储区的关系如下图
运行时存储区

内存优化一般是调节catalina.bat/catalina.sh里面的JAVA_OPTS的值。例如

JAVA_OPTS='-Xms256m -Xmx512m' 
JAVA_OPTS='-Xms1024m -Xmx2048m -XX:PermSize=256M -XX:MaxNewSize=256m -XX:MaxPermSize=256m'

【参数说明】

  • -server 启用jdk 的 server 版,JVM内部有特殊处理
  • -Xms 是指设定程序启动时占用内存大小。JVM初始化堆的大小。一般来讲,大点,程序会启动的 快一点,但是也可能会导致机器暂时间变慢。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
  • -Xmx 是指设定程序运行期间最大可占用的内存大小。JVM堆的最大值。如果程序运行需要占 用更多的内存,超出了这个设置值,就会抛出OutOfMemory 异常。
  • -Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程 大约需要占用多少内存,可能会有多少线程同时运行等。
  • -XX:PermSize设置非堆内存初始值,默认是物理内存的1/64 。
  • -XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
  • -Dfile.encoding:默认文件编码
  • -XX:NewSize:设置年轻代大小
  • -XX:MaxNewSize:设置最大的年轻代大小
  • -XX:SurvivorRatio:设置新生代中1个Eden区与1个Survivor区的大小比值。在hotspot虚拟机中,新生代 = 1个Eden +2个Survivor。如果新生代内存是10M,SurvivorRatio=8,那么Eden区占8M,2个Survivor区各占1M。
  • -XX:PermSize:设置永久代(方法区)大小
  • -XX:MaxPermSize:设置最大永久代大小
  • -XX:NewRatio=4:指定老年代/新生代的堆内存比例。在hotspot虚拟机中,堆内存 = 新生代 + 老年代。设置为 4,则年轻代与终身代所占比值为 1:4,年轻代占整个堆栈的1/5。在设置了-XX:MaxNewSize的情况下,-XX:NewRatio的值会被忽略
  • -XX:MaxTenuringThreshold=10:设置垃圾最大年龄,默认为:15。如果设置为 0 的话,则年轻代对象不经过 Survivor 区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在 Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
  • -XX:+DisableExplicitGC:这个将会忽略手动调用 GC 的代码使得 System.gc() 的调用就会变成一个空调用,完全不会触发任何 GC

tomcat线程优化(server.xml)

线程优化主要是调节conf/server.xml里面的配置。

<!--连接器设置-->
<Connector 
port="8080" 
protocol=" org.apache.coyote.http11.Http11Nio2Protocol " --协议类型 
--设置bio    HTTP/1.1
--设置nio    org.apache.coyote.http11.Http11NioProtocol
--设置 nio2/aio   org.apache.coyote.http11.Http11Nio2Protocol
--设置 apr   org.apache.coyote.http11.Http11AprProtocol(需要额外进行安装,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能.必须要安装apr和native,直接启动就支持apr)
disableUploadTimeout="true"
keepAliveTimeout="20000"--长连接最大保持时间(毫秒),表示在下次请求过来之前,Tomcat 保持该连接多久,默认是使用 connectionTimeout 时间,-1 为不限制超时。
connectionTimeout="20000" --  网络连接超时,单位:毫秒,设置为 0 表示永不超时,这样设置有隐患的。通常可设置为 30000 毫秒,可根据检测实际情况,适当修改。
redirectPort="8443" –SSL请求的转发端口 
URIEncoding="UTF-8"--URL编码字符集
minSpareThreads="100" --默认初始化和保持空闲的线程数
enableLookups="false"--关闭DNS反向查询。是否反查域名,以返回远程主机的主机名,取值为:true 或 false,如果设置为false,则直接返回IP地址,为了提高处理能力,应设置为 false。
useURIValidationHack="false" --关闭不必要的检查
maxThreads="1000" --处理请求线程的最大数目 默认值为200  
acceptCount="1000" --所用可能的线程都在使用时传入连接请求的最大长度,一般与maxThreads相同即可。
disableUploadTimeout="true" –禁用上传时的超时机制。允许更长的超时连接。
maxPostSize=“1085760--以 FORM URL 参数方式的 POST 提交方式,限制提交最大的大小,默认是 2097152(2M),它使用的单位是字节。10485760 为 10M。如果要禁用限制,则可以设置为 -1。
maxConnections="1000"--接受和处理的最大连接数(默认nio/nio2 10000,apr 8192)
maxHttpHeaderSize="8192"--请求和响应http头的最大大小 8k
tcpNoDelay="true" –禁用Nagle算法,使得TCP无延迟。TCP协议中采用Nagle算法将多个小TCP包合并成一个大的TCP包,直到达到最大的size或者收到一个ACK才发送出去。
acceptorThreadCount=“2--用于接收连接的线程的数量,默认值是1。一般这个指需要改动的时候是因为该服务器是一个多核CPU,如果是多核 CPU 一般配置为 2
compression="on"--是否启用压缩 。HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求服务器对应资源后,从服务器端将资源文件压缩,再输出到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML ,CSS,Javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,压缩效率也很高。
PS:压缩会增加Tomcat负担,最好采用Nginx + Tomcat 或者 Apache + Tomcat 方式,压缩交由Nginx/Apache 去做。
compressionMinSize="2048" --压缩前数据最小值 2k byte
noCompressionUserAgents="gozilla,traviata" --设置哪些浏览器不压缩
compressableMimeType="text/html,text/xml,text/css,application/javascript,text/plain" --设置压缩的文件类型
/>

三:Tomcat IO优化

JAVA的IO模型:

  • 同步阻塞IO(JAVA BIO) 同步并阻塞,服务器实现模式为一个连接一个线程(one connection one thread想想都觉得恐怖,线程可是非常宝贵的资源),当然可以通过线程池机制改善.
  • JAVA NIO:又分为同步非阻塞IO,异步阻塞IO与BIO最大的区别one request one thread.可以复用同一个线程处理多个connection(多路复用).
  • 异步非阻塞IO(Java NIO2又叫AIO)
    主要与NIO的区别主要是操作系统的底层区别.可以做个比喻:比作快递,NIO就是网购后要自己到官网查下快递是否已经到了(可能是多次),然后自己去取快递;AIO就是快递员送货上门了(不用关注快递进度)。

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解.
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持.
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持.在server.xml中修改connector的protocol可以实现对Tomcat的IO切换。

猜你喜欢

转载自blog.csdn.net/Hemk340200600/article/details/79183633