《软件性能测试、分析与调优实践之路》学习笔记

408 阅读7分钟

Part-1 性能测试、分析与调优基础

一、性能测试的目的

  1. 获取系统各项性能指标
  2. 发现性能瓶颈和性能问题,进行分析、调优

二、性能测试的分类

  1. 性能测试

    获取在正常负载下的各项性能指标

  2. 负载测试

    获取系统在不同负载下的性能变化曲线,找到性能的拐点

  3. 压力测试

    获取在高负载下的性能表现,找到系统能承受的最大负载和吞吐率

  4. 基准测试

    采集各项性能指标作为后续版本性能的对比

  5. 稳定性测试

    正常或略高于正常负载,对系统进行长时间测试,检测系统是否稳定运行,以及观察性能指标变化

  6. 扩展性测试

    先测试单台服务器的处理能力,慢慢增加服务器数量,测试处理能力是否稳定增强

三、性能测试的场景

  1. 真实业务场景
  2. 测试场景
  3. 单场景(单个业务流程)
  4. 混合场景(多个业务流程)

四、性能测试的指标

响应时间

响应时间=网络时间+程序处理时间

TPS/QPS
  • TPS 每秒处理的事务数
  • QPS 每秒查询数
  • QPS > TPS
并发用户
  • 绝对并发,某一时间点,向服务器发出请求的用户数
  • 相对并发,某一时间段内,向服务发出请求的用户数
PV/UV(每个用户的平均浏览量)
  • PV 页面浏览/点击量,多次浏览/点击,数量可以累加
  • UV,唯一访客,一段时间内,同一访客只计算一次
点击率
  • 每秒的页面点击数
  • 在性能测试中,一般不发起静态请求(对静态资源的请求,如图片、js、css),静态资源通常不经过应用服务器处理,或者走CDN
吞吐量

系统在单位时间内处理请求的数量

资源开销

每个请求/事务,对CPU、内存、IO、网络带宽的消耗

五、常见的性能问题

负载不均

在并发的情况下,每台服务器收到的并发压力不均匀,部分服务器压力过大导致性能下降,部分服务器压力过小导致资源浪费

内存泄漏

程序在每次执行完后不主动释放内存,导致内存不断增加,耗光服务器物理内存,程序运行变慢,最终因为无法申请到内存,退出运行

连接泄漏

数据库连接、HTTP连接等,短连接应该用完就关闭、释放

线程安全

高并发、多线程处理过程中,多个线程先后更改数据,导致得到的数据是脏数据

死锁

多线程中发生,系统死锁、数据库死锁

架构扩展性问题

性能无法满足预期时,扩展了硬件资源,性能指标无法按照一定的线性规律快速递增

六、性能测试流程

  1. 需求分析
  2. 制定计划
  3. 测试方案
  4. 测试用例
  5. 搭建性能测试环境
  6. 构造测试数据
  7. 编写测试脚本
  8. 执行测试用例
  9. 分析测试结果,编写测试报告
  10. 性能瓶颈分析与调优

七、性能调优分析方法

  1. 分层分析

    根据系统架构进行分层分析

  2. 科学论证

    发现问题—问题假设—预测—验证—分析

  3. 追溯归纳总结

    追溯最近的变动,代码、版本、数据库、配置、网络、服务器硬件等

八、性能调优技术

缓存调优
  1. 提高缓存命中率

  2. 防止缓存穿透

  3. 控制缓存失效时间

  4. 缓存监控分析

  5. 防止缓存雪崩

    缓存雪崩:在异常情况下,缓存数据全部丢失,导致大量请求需要从数据库获取数据,数据库压力过大造成崩溃

同步转异步推送
  1. 解决请求的阻塞等待问题
  2. 同步:系统受到请求后,处理完成后才返回响应结果
  3. 异步:系统受到请求后,立即把请求接受成功返回给调用方,处理完成后,再将处理结果推送给调用方
业务拆分
  1. 将系统中的复杂业务调用,拆分成多个简单业务调用
  2. 好处:高并发业务不影响低并发业务的性能,扩展更有针对性,避免资源浪费
  3. 调用高的业务,独立子系统
  4. 调用接近的业务,按业务归类到一个子系统中
任务分解与并行计算
  1. 通过并行计算提高处理能力
  2. 一个任务拆分成多个子任务,并行计算处理,将计算结果合并在一起返回
索引与分库分表
  1. 数据量正常,使用数据库索引查询

  2. 数据量庞大,分表分库

    优点:单次查询需要查询多个分表,可以通过多线程并行处理,提高查询效率

  3. 分库分表方式:冷热数据分离、按时间维度区分

Part-2 服务器的性能监控与分析

Linux常用性能监控命令

vmstat
mpstat
pidstat
netstat
lsof -i:端口号 查看某个端口下的网络连接情况
free
top

Part-3 应用中间件的性能分析与调优

Tomcat容器的I/O分析

同步阻塞I/O
  1. 用户线程发起数据读取请求
  2. 操作系统内核收到请求,处理数据
  3. 数据处理完成后,将数据拷贝到用户空间
  4. 用户态将数据返回给用户线程
同步非阻塞I/O
  1. 用户线程发起数据读取请求
  2. 操作系统内核收到请求,立即返回数据当前状态,处理数据
  3. 用户线程轮询请求,内核返回数据当前状态
  4. 处理完成后,内核将数据拷贝到用户空间
  5. 用户线程从用户空间读取数据
异步非阻塞I/O
  1. 用户线程发起数据读取请求
  2. 操作系统内核收到请求,立即返回请求已收到,处理数据
  3. 数据处理完成后,将数据拷贝到用户空间,并通知用户线程
  4. 用户线程从用户空间读取数据
多路复用I/O
  1. 传统处理方式:一个I/O请求开启一个进程/线程,高并发下,需要开启大量进程/线程,耗费服务器硬件资源
  2. 多路复用:开启一个进程,通过记录I/O流的状态,管理多个I/O,节省服务器资源

Part-4 Java应用程序的性能分析与调优

JVM

java虚拟机,运行在操作系统上的一个程序

类加载器

将.class字节码文件加载到内存,供JVM使用

过程:加载—连接(验证、准备、解析、初始化)—被调用—卸载

垃圾回收算法

根搜索

从GC ROOT开始,寻找引用节点,回收未被引用的节点

标记-清除

从GC ROOT开始扫描,标记存活的对象,回收未被标记的对象

标记-整理

从GC ROOT开始扫描,标记存活的对象,回收未被标记的对象,往左移动内存空间,更新指针

复制

将内存分成活动区和空闲区,从GC ROOT开始扫描,标记存活的对象,将存活的对象复制到空闲区内存,回收活动区内存

增量回收

将内存划分为多个区域,每次仅对某一个区域进行垃圾回收,优点,减少程序

end