常用指令与可视化调试工具
jps指令
Java版的ps命令,查看java进程及其相关的信息。
命令格式:jps [options] [hostid]
options参数解释:
-l : 显示进程id,显示主类全名或jar路径
-q : 显示进程id
-m : 显示进程id, 显示JVM启动时传递给main()的参数
-v : 显示进程id,显示JVM启动时显示指定的JVM参数
hostid : 主机或其他服务器ip
jinfo指令
常用指令之一,主要用来查看JVM参数和动态修改部分JVM参数的命令。
命令格式:jinfo [options]
options参数解释:
no options 输出所有的系统属性和参数
-flag 打印指定名称的参数
-flag [+|-] 打开或关闭参数
-flag = 设置参数
-flags 打印所有参数
-sysprops 打印系统配置
jstat指令
常用指令之一,主要用来查看JVM运行时的状态信息,包括内存状态、垃圾回收等。
命令格式:jstat [option] VMID [interval] [count ]
VMID是进程id,interval是打印间隔时间(毫秒),count是打印次数(默认一直打印)。
option参数解释:
-class class loader的行为统计
-compiler HotSpt JIT即时编译器行为统计
-gc 垃圾回收堆的行为统计
-gccapacity 各个垃圾回收代容量(young,old,perm)和他们相应的空间统计
-gcutil 垃圾回收统计概述
-gccause 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因
-gcnew 新生代行为统计
-gcnewcapacity 新生代与其相应的内存空间的统计
-gcold 年老代和永生代行为统计
-gcoldcapacity 年老代行为统计
-printcompilation HotSpot编译方法统计
查看GC堆容量使用情况 jstat -gc 2708 200 10
0C幸存0区容量、S0U幸存0区已使用量、EC Eden区总量、EU Eden区已使用量、OC老年区总容量、OU老年区已使用总量、MC方法区总量、MU方法去已使用量、CCSC压缩空间总量、CCSU压缩已使用量、YGC 年轻代垃圾回收次数、YGCT 年轻代执行垃圾回收消耗时间、FGC Full GC垃圾回收次数、FGCT Full GC垃圾回收消耗时间、GCT 垃圾回收消耗总时间
查看GC堆百分比占比情况jstat -gcutil 2708 200 3
S0 幸存0区使用百分比、E Eden区使用百分比、O 老年代使用百分比、M 元数据区使用百分比、CCS 压缩使用百分比
示例:3次创建byte对象,GC垃圾回收情况,对象从年轻代晋升到老年代。
jstack指令
查看JVM线程快照的命令,线程快照是当前JVM线程正在执行的方法堆栈集合,定位线程出现长时间卡顿的原因,例如死锁,死循环等。
命令格式:jstack [options]
option参数解释:
-F 当使用jstack 无响应时,强制输出线程堆栈。
-m 同时输出java堆栈和c/c++堆栈信息(混合模式)
-l 除了输出堆栈信息外,还显示关于锁的附加信息,如死锁。
cpu占用过高问题排查
1)使用Process Explorer工具找到cpu占用率较高的线程
2)在thread卡中找到cpu占用高的线程id
3)线程id转换成16进制
4)使用jstack -l 查看进程的线程快照 根据16进制id找到对应线程
5)线程快照中找到指定线程,并分析代码
jmap指令
jmap可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列
命令格式:jmap [option] (连接正在执行的进程) 不加参数默认打印所有
option参数解释:
-heap 打印java heap摘要
-histo[:live] 打印堆中的java对象统计信息
-clstats 打印类加载器统计信息
-finalizerinfo 打印在f-queue中等待执行finalizer方法的对象
-dump: 生成java堆的dump文件
jhat指令
jhat是用来分析jmap生成dump文件的命令,jhat内置了应用服务器,可以通过网页查看dump文件分析结果,jhat一般是用在离线分析上。
命令格式 : jhat [option][dumpfile]
option参数解释:
-stack false: 关闭对象分配调用堆栈的跟踪
-refs false: 关闭对象引用的跟踪
-port : HTTP服务器端口,默认是7000 -debug : debug级别
-version 分析报告版本
jconsole 监控管理工具
java5开始,在JDK中自带的java监控和管理控制台,用于对JVM中内存,线程和类等的监控,是一个基于JMX的GUI性能监测工具。
VisualVM 可视化优化工具
VisualVM 是一个工具,它提供了一个可视界面,用于查看 Java 虚拟机 (Java Virtual Machine, JVM) 上运行的基于 Java 技术的应用程序(Java 应用程序)的详细信息,如果存在死锁等异常问题会直接警告,然后根据警告找到线程定位到对应代码。
六、GC日志分析
GC日志参数
GC日志是一个很重要的工具,它准确记录了每一次的GC的执行时间和执行结果,通过分析GC日志可以优化堆设置 和GC设置,或者改进应用程序的对象分配模式。
常用垃圾收集器参数
GC日志分析
比如日志格式如下
比如日志格式如下
进行抽象化
a: GC 或者是 Full GC
b: 用来说明发生这次 GC 的原因
c: 表示发生GC的区域,这里表示是新生代发生了GC,上面那个例子是因为在新生代中内存不够给新对象分配了,然后触发了 GC
d: GC 之前该区域已使用的容量
e: GC 之后该区域已使用的容量
f: 该内存区域的总容量
g: 表示该区域这次 GC 使用的时间
h: 表示 GC 前整个堆的已使用容量
i: 表示 GC 后整个堆的已使用容量
j: 表示 Java 堆的总容量
k: 表示 Java堆 这次 GC 使用的时间
l: 代表用户态消耗的 CPU 时间
m: 代表内核态消耗的 CPU 时间
n: 整个 GC 事件从开始到结束的墙钟时间(Wall Clock Time)
大对象直接进入老年代,虚拟机提供一个参数 -XX:PretenureSizeThreshold 用来设置直接在老年代分配的对象的大小,如果对象大于这个值就会直接在老年代分配,避免Eden区和Survivor区复制消耗性能。
日志分析工具
GC日志可视化分析工具GCeasy(在线的GC日志分析器 在线地址https://gceasy.io/index.jsp)和GCviewer(免费开源软件),通过这些工具可以直接看到JVM各个分代的内存使用情况、垃圾回收次数、垃圾回收的原因、垃圾回收占用的时间、吞吐量等。
七、JVM调优实战
Tomcat与JVM调优
修改tomcat-users.xml 配置tomcat管理用户
Apache Jmeter测试工具
Apache Jmeter是开源的压力测试工具,我们借助于此工具进行测试,将测试出tomcat 的吞吐量等信息。
下载地址:http://jmeter.apache.org/download_jmeter.cgi
调整tomcat参数进行优化
1) 禁用AJP服务,AJP是定向包协议,Tomcat在 server.xml 中配置了两种连接器,一种监听8080,负责和其他的HTTP服务器建立连接,一种监听8009,负责和其他的HTTP服务器建立连接,第二种如要要用可以配置nginx实现负载均衡,所以可以直接注释掉。
2) 设置执行器(线程池),频繁地创建线程会造成性能浪费,所以使用线程池来优化,通过修改server.xml文件
3) 设置最大等待队列,默认情况下,请求发送到tomcat,如果tomcat正忙,那么该请求会一直等待,可以设置超过就不等待,请求失败,降低服务器负载。
4) 设置nio2的运行模式,tomcat8以前默认是bio,同步并阻塞,性能低下无优化,8之后是nio,同步非阻塞,还有个性能更高的nio2,异步非阻塞,可以更改设置。
调整JVM参数进行优化
1) 设置并行垃圾回收器,提高并发效率。
修改catalina.sh
2) 通过GC easy查看GC日志文件,查看年轻代和老年代空间大小分配是否合理并调整优化。
修改catalina.sh
3) 设置G1垃圾收集器,G1的性能是非常强悍的,能用G1的情况下优先使用,能极大提高程序运行性能。
修改catalina.sh
八、Linux优化
Linux性能优化概述
Linux性能的基本指标、工具,相应的观测、分析和调优方法。包括CPU性能、磁盘I/O性能、内存性能及网络性能。其实最终目的就是为了实现高并发和吞吐快,也就是延时和吞吐。
调优的步骤
1) 选择指标评估应用程序和系统性能
2) 设置性能目标
3) 进行性能基准测试
4) 性能分析,如果未达到目标,分析定位瓶颈。
5) 根据分析结果优化应用程序和系统
6) 进行性能监控和阀值警告机制
性能优化方法论
应用程序维度:吞吐量和请求延迟评估应用程序性能
系统资源维度:CPU使用率评估系统CPU使用情况
多个性能问题同时存在,二八原则,即优先优化问题最大最重要的,也是提示最大的。
多种优化方案,选择提升性能最明显的,复杂的优化方案会降低程序可维护性。
Linux优化-CPU优化(性能统计)
1)平均负载率
单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,平均负载率高不一定CPU使用率也高,比如I/O密集架进程,等待I/O。
可运行状态的进程:正在使用CPU和等待CPU的进程,ps指令,处于R状态的进程。
不可中断状态的进程:处于内核态关键流程中的进程,如I/O响应,ps指令,处于D状态的进程。
查看负载命令uptime
主要看最后三个值,也就是1分钟,5分钟,15分钟平均负载,相差不大说明系统负载稳定。
平均负载最理想的情况是等于CPU个数,从上图来说,如果系统只有1个CPU,1分钟的负载率就高达501%,说明有多个进程正在争抢这个CPU,已经超载,最佳方案是平均负载不能高于CPU数量的70%。
Linux系统压力测试工具Stress
Linux系统性能监控和分析工具Sysstat
mpstat命令:实时查看每个CPU的性能指标以及所有CPU的平均指标。
pidstat命令:实时查看进程的CPU、内存、I/O以及上下文切换等性能指标。
2)上下文切换
Linux是多任务操作系统,支持远大于CPU数量的任务同时运行,通过频繁的上下文切换,将CPU轮流分配给不同任务。CPU上下文切换就是保存当前任务的上下文,即CPU寄存器和程序计数器,加载新任务的上下文到CPU寄存器和程序计数器中,调转程序计数器所指的新位置,运行新任务,保存的上下文存储在系统中,通过任务重新调度执行加载。
上下文切换时机:
CPU会给每一个进程划分时间片,时间片耗尽上下文切换。
进程资源不足,如内存不够,就挂起
通过sleep函数休眠
有优先级更高的进程
发生故障,硬件中断。
发生故障,硬件中断。
从Ring 0 内核空间即内核态到Ring 3用户空间即用户态权限递减,即Ring 0能访问所有。
进程的上下文切换:一个进程到另一个进程
系统调用:同一个进程运行,即上面模型图中的特权模式切换,即内核态和用户态切换,比如读取一个文件,先是把用户开发文件,保存用户态指令,然后切换到内核态执行,再切换回用户态响应结果。
进程上下文切换:进程是资源拥有的结伴单位,切换就两步,保存上下文,切换上下文。
CPU挑选进程运行原则:每个CPU都维护了一个等待队列,按优先级和CPU等待时间排序,即优先级和先入先出原则执行进程。
线程上下文切换:线程是调度的基本单位,切换分两种,两个线程属于不同进程和进程切换一致,属于同一进程,共有资源不动,只切换私有资源。
中断上下文切换:受到中断信号,保存当前进程,等待中断结束继续运行,中断优先级比进程上下文切换高,并发也不会同时发生。
通过vmstat工具分析上下文切换情况及中断次数
命令vmstat 3 5 即3秒打印一次结果一共输出5次
查看进程对应情况命令 pidstat -u -w 3
3)CPU使用率
单位时间内CPU的使用情况,百分比显示。CPU使用率=1-(空间时间/总CPU时间),性能工具是按间隔时间求平均得到使用率。
top(总体)、ps(所有进程)、pidstat(单个进程)是最常用性能分析工具
Linux优化-CPU优化(调优策略)
CPU优化分应用程序维度和系统的角度,即代码工程优化和系统参数设置优化。
应用程序优化:排除所有不必要操作保留核心逻辑
1) 编译器优化,大部分编译器都提高优化选项,开启之后,在编译阶段就能对工程优化,提高性能。
2) 减少循环的次数、减少递归、减少动态内存分配
3) 算法优化,使用复杂度更低的算法。
4) 异步处理,提高程序并发处理能力,避免程序因等待资源一直阻塞,比如把轮询替换为事件通知。
5) 多线程代替多进程,多线程之前的切换比多进程切换成本低
6) 多用缓存,经常访问的数据和计算过程的步骤放入缓存,加快程序处理速度。
系统角度:利用CPU缓存的本地性并控制进程的CPU使用情况
1) 进程优先级调整
2) 进程设置资源限制,避免过多消耗系统资源
3) 中断负载均衡,任何中断处理程序都会消耗大量CPU资源,把中断处理过程均衡分配到多个CPU上。
Linux优化-内存优化(性能统计)
要先知道内存的各个内存量,才能根据指标进行优化,分系统内存和进程内存。
系统内存使用情况 free命令 free -h -c 2 -s 2间隔两秒输出两次 并人性化输出所有信息
从头开始列名含义:总内存大小、已使用内存大小、未使用内存大小、共享内存大小、缓存和缓冲区内存大小、新进程可用内存大小(包含未使用和可回收内存)。
Buffer是对磁盘数据的缓存,Cache是文件数据的缓存,读写请求都可以使用。
缓存和缓冲区的缓存命中率越高,使用缓存带来的收益就会越高,应用程序的性能就会越好。
通过top指令查看进程内存
Linux优化-内存优化(调优策略)
1) 禁止Swap,使用本地内存空间,避免服务器因物理内存不够用,使用Swap分区空间。
2) 减少内存的动态分配,使用如内存池,大页等。
3) 尽量使用缓存和缓冲区来访问数据。如redis组件。
4) 使用cgroups限制进程内存使用情况。
5) 通过/proc/pid/oom_adj调整核心应用的oom_score,设置为0,保证内存紧张,核心应用不会被OOM杀死。
Linux优化-磁盘IO优化(性能统计)
文件数据的储存:超级块、索引节点区、数据块区
超级块:整个文件系统的状态
索引节点区:存储索引节点,便于查找
数据块区:存储文件的数据
1) 每秒IO数(IOPS):每秒磁盘连续读次数和连续写次数之和。
2) 吞吐量(Throughput):硬盘传输数据流的速度,即读写数据之和
3) 平均IO数据尺寸:吞吐量/IO数目
4) 磁盘活动时间百分比:磁盘处于活动时间的比率,即磁盘利用率。
5) 服务时间:磁盘进行读和写执行时间。
6) IO等待队列长度:等待磁盘处理的IO请求长度
7) 等待时间:磁盘读或写等待执行的时间
IO性能观测工具iostat,通过他查看磁盘的使用率、IOPS、吞吐量,使用命令iostat -d -x 1
Linux优化-磁盘IO优化(调优策略)
应用程序优化策略
1) 追加写代替随机写
2) 利用缓存IO降低IO次数
3) 使用redis外部缓存
4) 频繁读写同一块磁盘空间,使用mmap代替read/write,减少内存拷贝次数
5) 同步写场景,将请求合并,不要多次请求同步写入磁盘。
6) 多应用程序共享磁盘,使用cgroups进行限制
文件系统优化策略
1) 如果做了负载均衡,选择最适配的文件系统,如Ubuntu默认ext4,CentOS 7默认xfs
2) 优化文件系统配置
3) 优化文件系统缓存
磁盘优化策略
1) 选择更好的磁盘,如固态硬盘SSD代替机械硬盘HDD
2) 使用RAID把多块磁盘组合成一个矩阵逻辑磁盘
3) 选择最合适的IO调度算法,如虚拟机和SSD使用noop调度算法,数据库应用可以改为deadline算法
4) 对应用程序数据进行磁盘级别隔离
5) 读场景较多,增大磁盘预读数据
6) 如果对磁盘操作频繁,调整磁盘队列的长度,增大磁盘吞吐量