本文是基于jdk1.8,其他版本稍有不同

JVM参数类型

(1)标准参数
-help
-server -client
-version -showversion
-cp -classpath
(2)X参数
非标准化参数
-Xint:解释执行
-Xcomp:第一次使用就编译成本地代码
-Xmixed:混合模式,由JVM自己来决定是否编译成本地代码

(3)XX参数
非标准化参数
相对不稳定
主要用于JVM调优和Debug

XX参数分类

(1)Boolean类型
格式:-XX:[+-]表示启动或禁用name属性
比如:-XX:+UseConcMarkSweepGC
-XX:+UseG1GC
(2)非Boolean类型
格式:-XX:=表示name属性的值是value
比如:-XX:MaxGCPauseMillis=500
XX:GCTimeRatio=19

jps工具

查看java进程

#常用指令
jps
jps -l

jinfo工具

查看Java进程运行的JVM参数

#常用指令
jinfo -flag <JVM参数> pid

jstat工具

监控进程的类装载、内存、垃圾收集、JIT编译等运行数据
jstat <参数> pid time(ms) count

#每隔1s显示类装载信息,输出10次
jstat -class 14589 1000 10
#每隔1s显示gc信息,输出10次
jstat -gc 14589 1000 10
#每隔1s显示JIT编译信息,输出10次
jstat -compiler 14589 1000 10
jstat -printcompilation 14589 1000 10

-gc输出结果
S0C、S1C、S0U、S1U:S0和S1的总量与使用量
EC、EU:Eden区总量与使用量
OC、OU:Old区总量与使用量
MC、MU:Metaspace区总量与使用量
CCSC、CCSU:压缩类空间总量与使用量
YGC、YGCT:YoungGC的次数与时间
FGC、FGCT:FullGC的次数与时间
GCT:总的GC时间

查看JVM运行时的参数

(1)PrintFlagsFinal

java -XX:+PrintFlagsFinal -version

(2)jinfo

jinfo -flag MaxHeapSize 14589

JVM内存结构

内存溢出演示

@Controller
public class OutOfMemory {
List<User> list=new ArrayList<User>();
@RequestMapping("/memory")
public void memory() {
int i=0;
while(true) {
list.add(new User(i++,UUID.randomUUID().toString()));
}
}
}

为了更快的看出效果,设置JVM参数:-Xmx32M -Xms32M

导出内存映像文件

(1)内存溢出时自动导出
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./

(2)使用jmap命令手动导出

jmap -dump:format=b,file=heap <pid>

Tomcat优化

线程优化

相关文档:docs/config/http.html
(1)maxConnections:最大连接数,tomcat能够最大处理的最大连接数
(2)acceptCount:默认是100,如果请求超过了maxConnections,可以配置一个队列,将连接压到队列里。(不需要太大,太大没有意义)
(3)maxThreads:工作线程数,默认值是200,同一个时间点上能够同时处理的并发请求数
(4)minSpareThreads:最小空闲的工作线程。不能设置太小,万一请求突然变多,线程数来不及增加。

配置优化

(1)autoDeploy:当tomcat运行时,是否需要周期性检查有新的web应用,来部署新的应用。生产环境,建议设置为false
(2)enableLookups:是否需要tomcat进行DNS域名解析。生产环境,建议设置为false
(3)reloadable:是否需要tomcat监控/WEB-INF/classes/ and /WEB-INF/lib的变化。生产环境,建议设置为false
(4)tomcat有3中方式启动:bio、nio、apr
BIO:bio是阻塞式IO操作,使用java io技术,即每一个请求都要创建一个线程来进行处理。缺点:并发量高时,线程数较多,占资源
NIO:使用java nio技术,能够通过少量的线程处理大量的请求,nio是基于java中非阻塞IO操作的API实现,比传统的i/o处理方式有更高的并发运行性能
APR(Apache Portable Runtime/Apache可移植运行时库):apr是从操作系统级别解决异步IO问题,大幅度提高服务器的并发处理性能,也是Tomcat生产环境运行的首选方式
tomcat低版本是使用BIO的,tomcat8以后默认使用NIO方式,在service.xml文件中找到此处

<Connector port="8091" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

修改成下面这个,可以使用apr的模式启动

<Connector port="8091" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" redirectPort="8443" />

Session优化

如果没有使用原生的Session,并且页面是使用JSP写的,建议禁用Session

#JSP禁用Session
<% page session="false" %>

Nginx优化

配置线程数和并发数

worker_processes 4; #cpu
events {
worker_connections 10240; #每个进程打开的最大连接数,包含了nginx与客户端和nginx与upsteam之间的连接
multi_accept on; #可以一次建立多个连接
use epoll;
}

配置后端Server的长连接

upsteam server_pool{
server localhost:8080 weight=1 max_fails=2 fail_timeout=30s;
server localhost:8081 weight=1 max_fails=2 fail_timeout=30s;
keepalive 300; #300个长连接
}
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://server_pool/;
}

配置压缩

gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_proxied any;
gzip_types text/plain text/css application/javascript application/x-javascript application/json application/xml application/vnd.ms-fontobject application/x-font-ttf application/svg+xml application/x-icon;
gzip_vary on;
gzip_static on; #如果有压缩好的,直接使用

操作系统优化

#配置文件/etc/sysctl.conf
sysctl -w net.ipv4.tcp_syncookies=1 #防止一个套接字在有过多试图连接到达时引起过载
sysctl -w net.core.somaxconn=1024 #默认128,连接队列
sysctl -w net.ipv4.tcp_fin_timeout=10 #timewait的超时时间,系统默认时间较长,可以改小一点
sysctl -w net.ipv4.tcp_tw_reuse=1 #os直接使用tomeout的连接
sysctl -w net.ipv4.tcp_tw_recycle=0 #回收禁用
#配置文件/etc/security/limits.conf
* hard nofile 204800
* soft nofile 204800
* soft core unlimited
* soft stack 204800

其他优化

sendfile on; #减少文件在应用和内核之间拷贝
tcp_nopush on; #当数据包达到一定大小再发送
tcp_nodelay off; #有数据包随时发送

GC调优

常用参数

-Xms -Xmx:最小堆内存 最大堆内存
-XX:NewSize -XX:MaxNewSize:新生代大小 最大新生代大小
-XX:NewRatio -XX:SurvivorRatio:young区与old区的比例 Eden区域和Survivor区域
-XX:MetaspaceSize -XX:MaxMetaspaceSize:Metaspace区域大小 最大Metaspace区域大小
-XX:+UseCompressedClassPointers:是否启用压缩的类指针,启用之后就会产生CCS区域(默认占有1024M大小)
-XX:CompressedClassSpaceSize:设置压缩区域大小

垃圾回收算法

(1)标记-清除
定义:算法分为“标记”和“清除”两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有
缺点:效率不高,标记和清除两个过程的效率都不高。产生碎片,碎片太多会导致提前GC。
(2)复制
定义:它将可用内存按容量分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完时,它将还存活着的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。
优缺点:实现简单,运行高效,但是空间利用率低。
(3)标记-整理
定义:标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
优缺点:没有了内存碎片,但是整理内存比较耗时。

分带垃圾回收

Young区用复制算法
Old区对象存活时间较长,采用标记清除或标记整理算法

对象分配

对象优先在Eden区分配
大对象直接进入老年代:-XX:PretenureSizeThreshold
长期存活的对象进入老年代:-XX:MaxTenuringThreshold -XX:+PrintTenuringDistribution -XX:TargetSurvivorRatio

垃圾收集器

(1)串行收集器Serial:Serial、Serial Old
进行垃圾收集时,必须暂停所有工作线程,直到完成,即”Stop The World”;

-XX:+UseSerialGC -XX:+UseSerialOldGC

(2)并行收集器Parallel:Parallel Scavenge、Parallel Old,吞吐量优先
Server模式下的默认收集器

#开启参数
-XX:+UseParallelGC -XX:+UseParallelOldGC
#开启多少个GC线程
-XX:ParallelGCThreads=<N>
CPU>8 N=5/8
CPU<8 N=CPU个数

(3)并发收集器Concurrent:CMS、G1,响应时间优先

#开启参数
CMS: -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
G1: -XX:+UseG1GC
#CMS的相关参数
-XX:ConcGCThreads:并发的GC线程数
-XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩
-XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次
-XX:CMSInitiatingOccupancyFraction:Old区内存占用多少时触发FullGC,默认92%
-XX:+UseCMSInitiatingOccupancyOnly:是否动态调
-XX:+CMSScavengeBeforeRemark:FullGC之前先做YGC
-XX:+CMSClassUnloadingEnabled:启用回收Perm区

垃圾收集器的选择

(1)优先调整堆的大小让服务器自己来选择
(2)如果内存小于100M,使用串行收集器
(3)如果是单核,并且没有停顿时间的要求,串行或者JVM自己选
(4)如果允许停顿时间超过1秒,选择并行或者JVM自己选
(5)如果响应时间必须小于1秒,选择并发收集器

G1垃圾收集器

(1)定义
将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);
Region:内存分区
SATB:它是通过Root Tracing得到的,GC开始时后存活对象的快照
RSet:记录了其他Region中对象引用本Region中对象的关系,属于points-into结构(谁引用了我的对象)
(2)YoungGC
1)新对象进入Eden区
2)存活对象拷贝到Survivor区
3)存活时间达到年龄阈值时,对象晋升到Old区
而G1垃圾收集器不是FullGC,是MixedGC(回收所有Young和部分Old)
(3)MixedGC时机
InitiatingHeapOccupancyPercent:堆占有率达到这个值则触发global concurrent marking(全局并发标记),默认值45%
G1HeapWastePercent:在global concurrent marking标记之后,可以知道区有多少空间要被回收,在每次YGC之后和再次发生MixedGC之前,会检查垃圾占比是否达到此参数值,只有达到了,下次才会发生MixedGC

#MixedGC相关参数
G1MixedGCLiveThresholdPercent #Old区的region被回收时候的存活对象占比
G1MixedGCCountTarget #一次global concurrent marking之后,最多执行Mixed GC的次数
G1OldCSetRegionThresholdPercent #一次Mixed GC中能够被选入CSet的最多old区的region数量
-XX:+UseG1GC #开启G1
-XX:G1HeapRegionSize=n #region的大小,1-32M,2048个
-XX:MaxGCPauseMillis=200 #最大停顿时间
-XX:G1NewSizePercent -XX:G1MaxNewSizePercent #young区占比 young区最大占比
-XX:G1ReservePercent=10 #保留防止Survivor区to space溢出
-XX:ParallelGCThreads=n #SWT线程数
-XX:ConcGCThreads=n #并发线程数=1/4*并行

(4)注意
年轻代大小:避免使用-Xmn、-XX:NewRatio等显式设置Young区大小,会覆盖暂停时间目标
暂停时间目标:暂停时间不要太苛刻,其吞吐量是90%的应用程序时间和10%的垃圾回收时间,太苛刻会直接影响到吞吐量