Part-1 性能测试、分析与调优基础
一、性能测试的目的
- 获取系统各项性能指标
- 发现性能瓶颈和性能问题,进行分析、调优
二、性能测试的分类
-
性能测试
获取在正常负载下的各项性能指标
-
负载测试
获取系统在不同负载下的性能变化曲线,找到性能的拐点
-
压力测试
获取在高负载下的性能表现,找到系统能承受的最大负载和吞吐率
-
基准测试
采集各项性能指标作为后续版本性能的对比
-
稳定性测试
正常或略高于正常负载,对系统进行长时间测试,检测系统是否稳定运行,以及观察性能指标变化
-
扩展性测试
先测试单台服务器的处理能力,慢慢增加服务器数量,测试处理能力是否稳定增强
三、性能测试的场景
- 真实业务场景
- 测试场景
- 单场景(单个业务流程)
- 混合场景(多个业务流程)
四、性能测试的指标
响应时间
响应时间=网络时间+程序处理时间
TPS/QPS
- TPS 每秒处理的事务数
- QPS 每秒查询数
- QPS > TPS
并发用户
- 绝对并发,某一时间点,向服务器发出请求的用户数
- 相对并发,某一时间段内,向服务发出请求的用户数
PV/UV(每个用户的平均浏览量)
- PV 页面浏览/点击量,多次浏览/点击,数量可以累加
- UV,唯一访客,一段时间内,同一访客只计算一次
点击率
- 每秒的页面点击数
- 在性能测试中,一般不发起静态请求(对静态资源的请求,如图片、js、css),静态资源通常不经过应用服务器处理,或者走CDN
吞吐量
系统在单位时间内处理请求的数量
资源开销
每个请求/事务,对CPU、内存、IO、网络带宽的消耗
五、常见的性能问题
负载不均
在并发的情况下,每台服务器收到的并发压力不均匀,部分服务器压力过大导致性能下降,部分服务器压力过小导致资源浪费
内存泄漏
程序在每次执行完后不主动释放内存,导致内存不断增加,耗光服务器物理内存,程序运行变慢,最终因为无法申请到内存,退出运行
连接泄漏
数据库连接、HTTP连接等,短连接应该用完就关闭、释放
线程安全
高并发、多线程处理过程中,多个线程先后更改数据,导致得到的数据是脏数据
死锁
多线程中发生,系统死锁、数据库死锁
架构扩展性问题
性能无法满足预期时,扩展了硬件资源,性能指标无法按照一定的线性规律快速递增
六、性能测试流程
- 需求分析
- 制定计划
- 测试方案
- 测试用例
- 搭建性能测试环境
- 构造测试数据
- 编写测试脚本
- 执行测试用例
- 分析测试结果,编写测试报告
- 性能瓶颈分析与调优
七、性能调优分析方法
-
分层分析
根据系统架构进行分层分析
-
科学论证
发现问题—问题假设—预测—验证—分析
-
追溯归纳总结
追溯最近的变动,代码、版本、数据库、配置、网络、服务器硬件等
八、性能调优技术
缓存调优
-
提高缓存命中率
-
防止缓存穿透
-
控制缓存失效时间
-
缓存监控分析
-
防止缓存雪崩
缓存雪崩:在异常情况下,缓存数据全部丢失,导致大量请求需要从数据库获取数据,数据库压力过大造成崩溃
同步转异步推送
- 解决请求的阻塞等待问题
- 同步:系统受到请求后,处理完成后才返回响应结果
- 异步:系统受到请求后,立即把请求接受成功返回给调用方,处理完成后,再将处理结果推送给调用方
业务拆分
- 将系统中的复杂业务调用,拆分成多个简单业务调用
- 好处:高并发业务不影响低并发业务的性能,扩展更有针对性,避免资源浪费
- 调用高的业务,独立子系统
- 调用接近的业务,按业务归类到一个子系统中
任务分解与并行计算
- 通过并行计算提高处理能力
- 一个任务拆分成多个子任务,并行计算处理,将计算结果合并在一起返回
索引与分库分表
-
数据量正常,使用数据库索引查询
-
数据量庞大,分表分库
优点:单次查询需要查询多个分表,可以通过多线程并行处理,提高查询效率
-
分库分表方式:冷热数据分离、按时间维度区分
Part-2 服务器的性能监控与分析
Linux常用性能监控命令
vmstat
mpstat
pidstat
netstat
lsof -i:端口号 查看某个端口下的网络连接情况
free
top
Part-3 应用中间件的性能分析与调优
Tomcat容器的I/O分析
同步阻塞I/O
- 用户线程发起数据读取请求
- 操作系统内核收到请求,处理数据
- 数据处理完成后,将数据拷贝到用户空间
- 用户态将数据返回给用户线程
同步非阻塞I/O
- 用户线程发起数据读取请求
- 操作系统内核收到请求,立即返回数据当前状态,处理数据
- 用户线程轮询请求,内核返回数据当前状态
- 处理完成后,内核将数据拷贝到用户空间
- 用户线程从用户空间读取数据
异步非阻塞I/O
- 用户线程发起数据读取请求
- 操作系统内核收到请求,立即返回请求已收到,处理数据
- 数据处理完成后,将数据拷贝到用户空间,并通知用户线程
- 用户线程从用户空间读取数据
多路复用I/O
- 传统处理方式:一个I/O请求开启一个进程/线程,高并发下,需要开启大量进程/线程,耗费服务器硬件资源
- 多路复用:开启一个进程,通过记录I/O流的状态,管理多个I/O,节省服务器资源
Part-4 Java应用程序的性能分析与调优
JVM
java虚拟机,运行在操作系统上的一个程序
类加载器
将.class字节码文件加载到内存,供JVM使用
过程:加载—连接(验证、准备、解析、初始化)—被调用—卸载
垃圾回收算法
根搜索
从GC ROOT开始,寻找引用节点,回收未被引用的节点
标记-清除
从GC ROOT开始扫描,标记存活的对象,回收未被标记的对象
标记-整理
从GC ROOT开始扫描,标记存活的对象,回收未被标记的对象,往左移动内存空间,更新指针
复制
将内存分成活动区和空闲区,从GC ROOT开始扫描,标记存活的对象,将存活的对象复制到空闲区内存,回收活动区内存
增量回收
将内存划分为多个区域,每次仅对某一个区域进行垃圾回收,优点,减少程序
end