背景:公司要求项目引入SSO(Single Sign On),SSO对JDK版本要求最低是1.7,而目前机器使用的是1.6版本,需要升级JDK。
参考: Tomcat8安装和配置、优化 G1垃圾回收器 实战Java虚拟机
升级JDK
公司测试线上服务器安装的JDK版本是jdk1.6.0_45,我打算安装最新的Jre1.8.0_121。
JDK与JRE区别
JVM = Class loader system + Runtime data area + Execution Engine.
JRE = JVM + Java packages classes(like util, math, lang, awt, swing etc)+ Runtime libraries.
JDK = JRE + Development/debugging tools.
我并不需要在测试线上机器上打包编译,仅仅需要一个可供应用运行的环境,所以我选择下载Jre。
修改Tomcat Jre配置
修改Tomcat文件夹下bin/catalina.sh文件,文件头添加。
JRE_HOME=/XXX/jre1.8.0_121
这样在Tomcat启动时就会使用指定的Jre环境。
升级Tomcat
升级Tomcat到9.0.0.M17版本(该版本运行环境必须>=1.8)。
修改Tomcat文件夹下bin/catalina.sh文件,文件头添加。
CATALINA_HOME=Tomcat路径
$CATALINA_HOME/catalina.pid
Linux下启动、关闭Tomcat分别执行bin下startup.sh和shutdown.sh脚本。
如果执行shutdown.sh仍然无法停止Tomcat,可以修改shutdown.sh脚本。
//最后一行
exec "$PRGDIR"/"$EXECUTABLE" stop "$@"
//改为
exec "$PRGDIR"/"$EXECUTABLE" stop 10 -force
Tomcat优化
修改conf/server.xml文件。
<Executor name="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="500"
minSpareThreads="100"
maxQueueSize = "100"
prestartminSpareThreads="true"/>
参数说明:
- name:用于区分线程池属性,必须独一无二。
- namePrefix:线程池创建线程名称前缀。
- maxThreads:线程池最大值,默认值200。
- prestartminSpareThreads:默认false,只有true时minSpareThreads才会有效果。
- minSpareThreads:线程池最小值,默认25。
- maxQueueSize:最大的等待队列数,超过则拒绝请求,默认Integer.MAX_VALUE。
- className:默认值org.apache.catalina.core.StandardThreadExecutor,实现org.apache.catalina.Executor接口,最好不要修改。
- threadPriority:线程优先级,默认5。
- daemon:是否以守护线程运行,默认true。
- maxIdleTime:当线程池线程数量大于minSpareThreads时,一个空闲线程最大存活时间,默认1分钟。
- threadRenewalDelay:如果有ThreadLocalLeakPreventionListener配置,会监听请求是否停止;停止时,会更新线程,为了避免同一时刻更新所有线程,设置任意2个线程更新间隔时间,默认1秒。
<Connector
executor="tomcatThreadPool"
port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="20000"
maxConnections="10000"
redirectPort="8443"
enableLookups="false"
acceptCount="100"
maxPostSize="10485760"
compression="on"
disableUploadTimeout="true"
compressionMinSize="2048"
acceptorThreadCount="2"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript"
URIEncoding="utf-8"
/>
参数说明:
- protocol,默认HTTP/1.1,org.apache.coyote.http11.Http11Nio2Protocol(Tomcat8/9)org.apache.coyote.http11.Http11NioProtocol(Tomcat6/7)
- allowTrace:是否运行TRACE HTTP请求,默认false。
- asynTimeout:异步请求超时时间,默认30000(30秒)。
- enableLookups:默认false,禁用DNS查询功能。
- maxHeaderCount:header中参数个数,默认100。
- maxParameterCount:GET/POST请求中带有参数个数,默认10000个。
- maxPostSize:以FORM URL参数方式的POST提交方式,限制提交最大的大小,默认是2M;设置-1禁用限制。
- port:tcp端口,设置0则Tomcat随机找一个空闲端口使用。
- redirectPort:接收到SSL请求后重定向的端口号。
- URIEncoding:URI编码格式。
- acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认100。
- acceptorThreadCount:接受连接的线程数,默认值1。多核CPU最好设置成2。
- compressableMimeType:默认值text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,逗号分隔,HTTP compression参数来使用。
- compression:使用GZIP压缩来节省带宽,"on":打开,"off":关闭。
- compressionMinSize:默认值2048,compression设置"on"生效,输出数据压缩最小值。
- connectionTimeout:连接超时时间,默认60秒。
- connectionUploadTimeout:针对文件上传的超时时间,disableUploadTimeout参数必须设置为false。
- disableUploadTimeout:设置true禁止服务器对文件上传给予更长的超时时间。
- executor:指定执行器。
- maxConnections:服务器能接受和处理的最大连接数;当连接数到达该值时,服务接受连接但不处理,接受连接数据受acceptCount控制。NIO、NIO2默认值10000。
JVM优化
原先JVM参数配置:
-server -Xms8g -Xmx8g -Xmn1g -Xss2048K
-XX:PermSize=512m -XX:MaxPermSize=512m
-XX:ParallelGCThreads=8
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=10
-XX:CMSInitiatingOccupancyFraction=80 -Dxxx=xxx
参数说明:
- -server:使用Server模式运行程序,会尝试收集更多的系统性能信息,使用更复杂的优化算法对程序进行优化。
- -Xmx...m:设置JVM最大可用内存。
- -Xms...m:设置JVM最小可用内存,可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
- -Xmn..m:设置JVM年轻代内存大小。
- -Xss...k:设置线程栈大小。
- -XX:PermSize=...m:设置永久代大小。
- -XX:MaxPermSize=...m:设置最大永久代大小。
- -XX:+UseParNewGC:新生代使用ParNew回收器。
- -XX:+UseConcMarkSweepGC:老年代使用CMS。
- -XX:ParallelGCThreads=.:ParNew回收器工作时线程数量,CPU数量小于8时,值等于CPU数量;CPU大于8时,值为3+(5*CPU_COUNT)/8。
- -XX:+UseCMSCompactAtFullCollection:CMS是一个标记清除回收器,会产生内存碎片,该设置在垃圾收集完成后,进行一次内存碎片整理。
- -XX:CMSInitiatingOccupancyFraction:指定当老年代空间使用率达到多少时,进行一次CMS垃圾回收。
- -XX:SurvivorRatio=.:年轻代分为eden+2survivor(from,to),比值代表eden/survivor的值。
- -XX:MaxTenuringThreshold=..:新生代对象存活次数(经过GC),晋升老年代。
- -Dxxx=xxx:设置应用需要的参数。
CMS(Concurrent Mark Sweep)并发标记清除,多次垃圾回收之后会产生内存碎片,需要在多次GC之后进行一次内存碎片整理。
G1(Garbage-First)是JDK 1.7中正式使用全新的垃圾回收器,G1回收器拥有独特的垃圾回收策略;从分代上看,G1依然属于分代垃圾回收器,会区分年轻代和老年代;但从堆结构上看,它不要求整个年轻代、老年代都连续;使用了分区算法。
G1特点:
- 并行性: G1在回收期间,可以由多个GC线程同时工作,有效利用多核计算能力。
- 并发性: G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此一般来说,不会在整个回收期间完全阻塞应用程序。
- 分代GC: G1依然是一个分代收集器,但是和之前回收器不同,同时兼顾年轻代和老年代;对比其他回收器,他们或工作在年轻代或老年代。
- 空间整理: G1在回收过程中,会进行适当的对象移动,减少空间碎片。
- 可预见性: 由于分区的原因,G1可以只选取部分区域进行内存回收,这样缩小了回收后的范围,因此对于全局停顿也能得到较好的控制。
新的JVM参数:
-server -Xms8g -Xmx8g -Xss2048K -XX:+UseG1GC
-XX:MaxGCPauseMillis=500 XX:InitiatingHeapOccupancyPercent=55
-XX:ParallelGCThreads=10 -XX:+DisableExplicitGC
把JVM参数配置在bin/catalina.sh文件头中。
JAVA_OPTS="xxx"
G1参数说明:
- -XX:+UseG1GC:使用 G1 (Garbage First) 垃圾收集器.
- -XX:MaxGCPauseMillis=n:设置最大GC停顿时间(GC pause time)指标(target). 这是一个软性指标(soft goal), JVM 会尽量去达成这个目标.
- -XX:InitiatingHeapOccupancyPercent=n:启动并发GC周期时的堆内存占用百分比. G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示"一直执行GC循环". 默认值为 45.
- -XX:G1ReservePercent=n:设置堆内存保留为假天花板的总量,以降低提升失败的可能性. 默认值是 10.
- -XX:G1HeapRegionSize=n:使用G1时Java堆会被分为大小统一的的区(region)。此参数可以指定每个heap区的大小. 默认值将根据 heap size 算出最优解. 最小值为 1Mb, 最大值为 32Mb.