目录
1.3.2 通过JMeter脚本,压测JForum, 进行CPU和内存诊断
1. 性能诊断
1.1 性能测试分类
1.1.1 前端
(1)App性能:App本身 ,接口(后端)
(2)小程序性能
(3)PC
(4)TW
1.1.2 后端
(1)http接口
(2)rpc接口
补充:什么是RPC?
RPC(Remote Procedure Call)是远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。
1.1.3 中间件
(1)db
(2)mq (消息中间件)
(3)nginx
1.1.4 重点关注:http接口测试
(1)监控指标
1)CPU
2)Memory
3)Network
4)IO
5)JVM:线程状态,堆栈信息,垃圾回收,内存泄漏/内存溢出(大对象)
(2)用户指标
1)RT(Response Time) 响应时间
2)TPS/QPS 每秒事务数
3) 并发用户数
4)思考时间
5)ERROR rate
1.2 诊断定位
1.2.1 CPU问题排查套路
(1)排查通用套路
1)发现CPU高的进程,一般来说是我们的被测应用
2)通过进程找对应消耗CPU高的线程
3)占用CPU高的线程在干嘛(进制转换,做映射)
(2) Windows环境1
1)发现某个应用程序(JAVA 后端应用)占用CPU比较多。
2)使用Process Explorer查看对应进程的线程信息,如下图。
3)找到占用CPU比较多的线程的TID。
4)将3中的TID转换为16进制 -> ${tid16}。
5)打开jvisualVM工具,dump出线程信息,查找${tid16}。
6)反编译/直接看代码定位问题。
(3) Windows环境2
1)发现某个应用程(JAVA 后端应用)序占用CPU比较多。
2)使用Process Explorer查看对应进程的线程信息,如下图。
3)找到占用CPU比较多的线程的tid。
4)将3中的TID转换为16进制 -> ${tid16}。
5)jstack ${pid} > pid.log 。(跟上一种方法的区别)
6)在 pid.log 中查找${tid16}相关堆栈信息。
7)反编译/直接看代码定位问题。
(4)Linux环境
1)通过top发现应用程序(JAVA 后端应用)占用CPU比较多的进程pid。
2)使用 top -Hp ${pid} 查看对应进程的线程信息。 结果列表中,看CPU和Time+(该线程实际耗时)
3)找到占用CPU比较多的线程的TID
4)将3中的TID通过命令 printf "%X\n" ${tid} 转换为16进制 -> ${tid16}
5)jstack ${pid} > pid.log
6)在 pid.log 中查找${tid16}相关堆栈信息
7)反编译/直接看代码定位问题
(5)补充知识点
1) cpu工作是分片的。简单说就是某个时间节点,只会执行一个任务。让人感觉很多任务同时进行,是因为把时间分片了,时间分片很小,让人感觉不出来区别,所以会觉得每个时刻都有很多任务同时进行。
2)topcpu脚本。用来自动获取多个线程信息,并自动完成一些转换(比如进制转换等): ./topcpu.sh -p ${pid} 5(表示要展示的个数)
1.2.2 内存问题排查套路
(1)JVM
1)CPU和内存的交互
---内存存在的意义:cpu非常快,物理磁盘慢,内存的速度介于两者之间。
---高速缓存的意义:内存越来越跟不上cpu的速度,因此在cpu和内存之间加了高速缓存。
---延伸:volatile。一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,则就具备了两层语义:一是保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。二是禁止进行指令重排序。
---常说的堆栈,其实就是指栈。
---思考: 用两个栈来模拟队列。
---常见的八种数据结构。
---堆涉及内存泄漏等,是我们比较关注的信息。
---配置jvm内存,用来测试内存溢出。
2)5大内存区域
定义:Java内存模型(Java Memory Model, JMM), 就是一种复合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java路径在各种平台下对内存的访问都能保证效果一致的机制和规范。
程序计数器(独有)
本地方法栈:底层调用C或者C++, 管理用另种语言写的方法的调用情况(独有)
Java栈(虚拟机栈):Java应用程序相关的(独有)
堆:new出来的对象放在堆里。堆是所有线程共享的,同时伴有线程安全的问题,所以可能会对一些对象上锁。重点!!!(共有)
方法区:存储反射时的一些class类,对象(共有)
(2)内存异常
1)StackOverflowError:堆栈溢出
2)OutOfMemoryError:内存溢出
(3)如何判断一个对象是否可以被回收
思考:如何判断哪些可以被可以被回收
1)引用计数法: 深入理解一下!!!
存在一定缺陷: 循环引用
2)根搜索法 / 可达性分析法:
通俗的说,就是某个对象/方法A,从最开始的对象/引用等,可以有一条路径比如getXXX到达A, 那么A就是可达的,就不会被回收。
GC Roots
虚拟机栈中引用的对象,就是平时说的Java对象
方法区中的静态属性引用的对象,一般是static修饰的对象
方法区中引用的对象
本地方法栈JNI引用的对象
3)GC算法
(4)堆区内存分类 - 怎么回收对象
1) 标记 / 清楚算法(祖先)
2)年轻代:复制算法
分几个区: Eden,FromServivor, ToServivor.
对象先放Eden区,满了之后放入Servivor
当一个对象连续存活17次之后,就放到年老区里
3)年老代:标记 / 整理算法
年轻代和年老代,分别用不同的算法来进行回收。
(5)监控年轻代、年老代、元数据空间变化情况
jstat查看堆内存整体使用情况:jstat -gcutil $pid 1000
jmap查看堆内存使用详情: jmap -heap $pid
jmap去dump对象详情:jmap -dump:format=b,file=${fileName}.dump $pid
1) jstat查看堆内存整体使用情况:jstat -gcutil $pid 1000
解析:
结果中,S0和S1代表两个servivor, E代表Eden区,O代表年老区,YGC年轻代的回收等信息
1000表示间隔1秒
这个命令的功能类似jvisualvm中的visualVM插件的功能
2)jmap查看堆内存使用详情: jmap -heap $pid
解析:展示该进程的内存信息,线程信息, Eden区,年老代等等
3) jmap去dump对象详情:jmap -dump:format=b,file=${fileName}.dump $pid
(6)JVM内存问题排查套路
1)通过命令导出dump文件: jmap -dump:format=b,file=${fileName}.dump $pid
---实现了 dump 堆内存对象详情
---在哪个目录下操作,导出的文件就在该目录下
2)将步骤1中的dump结果导入到MAT工具中进行分析。
3)查找大对象(和我们写的代码相关的)并进行分析。
4)常用选项:
---Biggest Objects By Retained Size
---Histogram
---Dominator Tree
---Top Consumer
---Leak Suspects
5)内存问题,因为都是基于JVM, 所以最常推荐去看大对象。
---Biggest Objects By Retained Size
---Histogram
---Dominator Tree
---Top Consumer
---Leak Suspects
1.3 练习:JForum环境准备
1.3.1 JForum环境配置 (配置在tomcat中)
(1)下载解压classes.7z。将解压出来的classes文件替换原来老的classes。
路径为: ${TOMCAT_HOME}\webapps\jforum-1.1.9\WEB-INF\classes
(2)启动Tomcat。
(3)编写JMeter脚本,脚本要求:访问随机板块和最新主题, 3个并发线程。
(4)执行脚本定位问题。
(5)延伸: 在centOS7中配置好环境,操作一遍。
1.3.2 通过JMeter脚本,压测JForum, 进行CPU和内存诊断
略