乐趣区

关于tomcat:Tomcat优化你值得拥有

最艰难的事件就是意识本人!
集体网站,欢送拜访!

前言:

Tomcat 作为 Web 利用的服务器,目前绝大多数公司都是用其作为应用服务器的;应用服务器的执行效率会影响零碎执行,这里会讲 Tomcat 怎么进行配置能进步解决性能;除此之外也必然会提到对应的 JVM 参数的优化的一些教训。

本文为 转载文章,原文地址:系统优化怎么做 -Tomcat 优化

Tomcat 的运行模式:

运行模式分 3 种模式:

  • bio:默认的模式,效率比拟低
  • nio:优化时应用的模式
  • apr:对系统配置有一些比拟高的要求

确认 Tomcat 运行模式:

查找配置文件 server.xml,在 tomcat 下的门路:conf 目录下;

Executor 为自定义配置 Tomcat 线程池:

<Executor name="tomcatThreadPool" 
namePrefix="catalina-exec-" 
maxThreads="1024" 
minSpareThreads="512" 
prestartminSpareThreads="true" />

要害配置:

maxThreads:

最大线程数,默认是 200

minSpareThread:

最小沉闷线程数,默认是 25

maxQueueSize:

最大的期待队列个数,超过则申请回绝默认值是 Integer.MAX_VALUE,个别不扭转。在某些紧急状态修复问题须要调整

连接器(Connector):

Connector 是连接器,负责接管客户的申请,以及向客户端回送响应的音讯。所以 Connector 的优化是重要局部。默认状况下 Tomcat 只反对 200 线程拜访,超过这个数量的连贯将被期待甚至超时放弃,所以咱们须要进步这方面的解决能力。

nio 配置:

配置文件 server.xml

<!-- 运行模式为 nio -->
<Connector port="14081" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
<!-- 连接器中连贯解决 应用下面自定义的 线程池中的线程 -->
executor="tomcatThreadPool" 
URIEncoding="UTF-8" 
compression="on"   
useBodyEncodingForURI="true" 
enableLookups="false" 
redirectPort="14443" />

影响性能的配置:

protocol:

org.apache.coyote.http11.Http11Protocol – 阻塞式的 Java 连接器
org.apache.coyote.http11.Http11NioProtocol – 不阻塞 Java 连接器
org.apache.coyote.http11.Http11AprProtocol – APR / native 连接器
抉择不阻塞 Java 连接器

enableLookups:

若是你想 request.getRemoteHost()的调用履行,以便返回的短途客户端的理论主机名的 DNS 查问,则设置为 true。设置为 false 时跳过 DNS 查找,并返回字符串的 IP 地址(从而进步性能)。默认场景下,禁用 DNS 查找

compression:

设置成 on,开启压缩

禁用 AJP 链接器:

应用 Nginx+tomcat 的架构,用不着 AJP 协定,所以把 AJP 连接器禁用
server.xml 正文掉以下配置:

  <Connector port="8019" protocol="AJP/1.3" redirectPort="8443" />

优化 JVM:

优化地位:/bin/catalina.sh

批改 JAVA_OPTS 参数,这里须要参照 机器配置,对 JVM 进行参数优化。

JDK1.7:
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=1024M -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:+DisableExplicitGC"
JDK1.8:
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=1024M -XX:+DisableExplicitGC"

留神:1.8 中曾经没有 永恒代 了,所以也就没有 没有 PermSize、MaxPermSize;Java8 中将永恒代改为了 元空间 了,JAVA8 里对 metaspace 能够在小范畴主动扩大永生代防止溢出。

参数阐明:

  • -Djava.awt.headless

没有设施、键盘或鼠标的模式。

  • -Dfile.encoding

设置字符集

  • -server

jvm 的 server 工作模式,对应的有 client 工作模式。应用“java -version”能够查看当前工作模式

  • -Xms1024m

初始 Heap 大小,应用的最小内存

  • -Xmx1024m

Java heap 最大值,应用的最大内存
教训: 设置 Xms 大小等于 Xmx 大小

  • -XX:NewSize=512m

示意新生代初始内存的大小,应该小于 -Xms 的值

  • -XX:MaxNewSize=1024M

示意新生代可被调配的内存的最大下限,应该小于 -Xmx 的值

  • -XX:PermSize=1024m

设定内存的永恒保留区域, 内存的永恒保留区域,VM 寄存 Class 和 Meta 信息,JVM 在运行期间不会革除该区域;个别状况下,此参数值应用默认即可,默认大小就够用了

程序加载很多 class 状况下,超出 PermSize 状况下:
JDK1.7 会抛出 java.lang.OutOfMemoryError: PermGen space 异样
JDK1.8 下会抛出 ERROR: java.lang.OutOfMemoryError: Metadata space 异样

  • -XX:MaxPermSize=1024m

设定最大内存的永恒保留区域
教训: 设置 PermSize 大小等于 MaxPermSize 大小

  • -XX:+DisableExplicitGC

主动将 System.gc()调用转换成一个空操作,即利用中调用 System.gc()会变成一个空操作, 防止程序员在代码里进行 System.gc()这种危险操作。System.gc() 除非是到了万不得也的状况下应用,都交给 JVM 吧

其余参数优化:

  • X:SurvivorRatio=2

年老代中 Eden 区与 Survivor 区的大小比值

  • -XX:ReservedCodeCacheSize=256m

保留代码占用的内存容量,无大的影响

  • -Xss1024k

单个线程堆栈大小值,缩小这个值能够生成更多线程,操作系统对于一个过程内的线程数是有限度的,经验值在 3000-5000 左右

  • -XX:+CMSParallelRemarkEnabled

CMS 垃圾回收算法,对响应工夫的重要性需要 大于 对吞吐量的要求,可能接受垃圾回收线程和利用线程共享处理器资源,并且利用中存在比拟多的长生命周期的对象的利用

  • -XX:+UseCMSCompactAtFullCollection

在应用 concurrent gc 的状况下, 避免 memoryfragmention, 对 live object 进行整顿, 使 memory 碎片缩小。

  • -XX:+UseCMSInitiatingOccupancyOnly

在 FULL GC 的时候,对年轻代的压缩。CMS 是不会挪动内存的,因而这个非常容易产生碎片,导致内存不够用,因而,内存的压缩这个时候就会被启用。减少这个参数是个好习惯。可能会影响性能, 然而能够打消碎片。

  • -XX:CMSInitiatingOccupancyFraction=60

应用 cms 作为垃圾回收, 应用 60%后开始 CMS 收集

  • -XX:+UseGCOverheadLimit

用来限度应用内存,如果不做管制,可能会报出
java.lang.OutOfMemoryError: GC overhead limit exceeded

  • -XX:+UseConcMarkSweepGC

应用 CMS 内存收集

  • -XX:+UseParNewGC

设置年老代为并行收集

  • -XX:+HeapDumpOnOutOfMemoryError
  • -XX:HeapDumpPath=/x/dump_tomcat.hprof

JVM 会在遇到 OutOfMemoryError 时拍摄一个“堆转储快照”,并将其保留在一个文件中。

  • -Xloggc:/xx/gc_tomcat.log

gc 的日志,如果该日志中呈现频繁的 Full GC 就是有相干的零碎问题,如果很少,阐明临时还算失常

  • -XX:+PrintGCDateStamps

输入 GC 的工夫戳(以基准工夫的模式)

  • -XX:+PrintGCDetails

输入 GC 的日志格局

  • -Dnetworkaddress.cache.ttl=60
  • -Dsun.net.inetaddr.ttl=60

设置 DNS 缓存工夫

  • -DautoStartup=false
  • -Dsun.net.client.defaultConnectTimeout=60000

连贯建设超时工夫

  • -Dsun.net.client.defaultReadTimeout=60000

内容获取超时设置

  • -Djmagick.systemclassloader=no

是否生成缩略图的一个框架的配置

  • -Djava.security.egd=file:/dev/./urandom

最佳实际:

export JAVA_OPTS="-server -showversion -Xms2000m -Xmx2000m -Xmn500m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:SurvivorRatio=2 -XX:ReservedCodeCacheSize=256m -Xss1024k -Djava.awt.headless=true -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseGCOverheadLimit -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tomcat_path/logs/dump_tomcat.hprof -Xloggc:/tomcat_path/logs/gc_tomcat.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCDetails -Dnetworkaddress.cache.ttl=60 -Dsun.net.inetaddr.ttl=60 -DautoStartup=false -Dsun.net.client.defaultConnectTimeout=60000 -Dsun.net.client.defaultReadTimeout=60000 -Djmagick.systemclassloader=no -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8"

常见 JVM 异样:

  1. java.lang.OutOfMemoryError: Java heap space —-JVM Heap(堆)溢出:

    JVM 在启动的时候会主动设置 JVM Heap 的值,其初始空间(即 -Xms)是物理内存的 1 /64,最大空间(-Xmx)不可超过物理内存。能够利用 JVM 提供的 -Xmn -Xms -Xmx 等选项可进行设置。Heap 的大小是 Young Generation 和 Tenured Generaion 之和。在 JVM 中如果 98% 的工夫是用于 GC,且可用的 Heap size 有余 2% 的时候将抛出此异样信息。

    解决办法:

    • 首先查看代码,是否存在创立了大量无用对象,且其被援用着,无奈被 GC 回收 的代码;
    • 手动设置 JVM Heap(堆)的大小;
  2. java.lang.OutOfMemoryError: PermGen space —- PermGen space 溢出:

    jdk1.8 抛出 ERROR: java.lang.OutOfMemoryError: Metadata space 异样
    PermGen space 的全称是 Permanent Generation space,是指内存的永恒保留区域。为什么会内存溢出,这是因为这块内存次要是被 JVM 寄存 Class 和 Meta 信息的,Class 在被 Load 的时候被放入 PermGen space 区域,它和寄存 Instance 的 Heap 区域不同,sun 的 GC 不会在主程序运行期对 PermGen space 进行清理,所以如果你的 APP 会载入很多 CLASS 的话,就很可能呈现 PermGen space 溢出。

    解决办法:手动设置 MaxPermSize 大小;

  3. java.lang.StackOverflowError —- 栈溢出:

​ 栈溢出了,JVM 仍然是采纳栈式的虚拟机。函数的调用过程都体现在堆栈和退栈上了。调用构造函数的“层”太多了,以致于把栈区溢出了。通常来讲,个别栈区远远小于堆区的,因为函数调用过程往往不会多于上千层,而即使每个函数调用须要 1K 的空间(这个大概相当于在一个 C 函数内申明了 256 个 int 类型的变量),那么栈区也不过是须要 1MB 的空间。通常栈的大小是 1-2MB 的。

解决办法: 代码中递归也不要递归的档次过多;

❤不要遗记留下你学习的脚印 [点赞 + 珍藏 + 评论]嘿嘿ヾ

所有看文章不点赞都是“耍流氓”,嘿嘿ヾ (◍°∇°◍)ノ゙!开个玩笑,动一动你的小手,点赞就完事了,你每个人出一份力量(点赞 + 评论) 就会让更多的学习者退出进来!非常感谢!~ω~=

退出移动版