1. 性能测试攻略

提前发现性能瓶颈,保障系统性能稳定。

1.1 微基准性能测试

精准定位到某个模块或者某个方法的性能问题。
适合做功能模块或方法不同实现方式下的性能对比。

1.2 宏基准性能测试

综合测试,需要考虑测试环境测试场景测试目标

1.2.1 测试环境

  • 需要模拟线上真实环境

    1.2.2 测试场景

  • 确定在测试某个接口时,是否有其他业务接口同时也在平行运行,造成干扰

  • 如有干扰,需重视,一旦忽视,结果就会出现偏差

    1.2.3 测试目标

  • 性能测试要有目标,可通过吞吐量及响应时间来衡量是否达标

    • 不达标,进行优化
    • 达标,继续加大测试并发数,探底接口的TPS,这样可以深入了解到接口性能
  • 还要循环测试可能导致性能问题的接口
    • 观察各个服务器的CPU、内存及 I/O 使用率变化

      1.3 性能测试要注意的问题

      1.3.1 热身问题

      Java文件编译成 class文件后,机器无法直接执行class文件中的字节码,需要通过解释器将字节码转换成本地机器码,为了节约内存和执行效率,代码最初执行时,解释器先解释执行。 随着代码被执行次数增多,当虚拟机发现某个方法或代码块运行特别频繁,就会认为是热点代码 (Hot Spot Code)。为了提高执行效率,运行时,通过即时编译器(JIT compiler, just-in-time compiler)把这些代码编译成与本地平台相关的机器码,并进行各层次优化,然后存储在内存中,之后每次执行直接从内存中获取。

在刚开始执行阶段,虚拟机会花费很长时间来全面优化代码,后面可能以最高性能执行。这就是热身过程,如果在性能测试,热身时间过长,会导致第一次访问速度过慢,可以考虑先优化再测试。

1.3.2 性能测试结果不稳定

测试时,伴随着很多不稳定因素

  • 机器其他进程影响
  • 网络波动
  • 每阶段JVM垃圾回收的不同

多次测试,将结果求平均,或者统计一个曲线图,只要保证平均值在合理范围内,波动不大,性能测试算是通过的

1.3.3 多JVM情况下的影响

服务器有多个Java应用服务,部署在不同的Tomcat下,意味着服务器有多个JVM。
任意一个JVM都有整个系统的资源使用权。
应该尽量避免线上环境中一台机器部署多个JVM的情况

2. 合理分析结果,制定调优策略

测试后,需要输出一份性能测试报告,帮助分析系统性能测试情况。
测试结果需要包含:

  • 接口平均、最大和最小吞吐量
  • 响应时间
  • 服务器的CPU
  • 内存
  • I/O
  • 网络 I/O使用率
  • JVM 的 GC 频率等

观察调优标准,发现性能瓶颈,再通过自下而上的方式分析查找问题

  • 首先从操作系统层面
    • 查看系统的 CPU、内存、I/O、网络使用率是否存在异常
    • 通过命令查找异常日志
    • 通过分析日志,找到瓶颈原因
  • 从Java 应用的 JVM 层面
    • 查看 JVM 的垃圾回收频率以及内存分配情况是否存在异常
    • 分析日志,找到瓶颈
  • 查看应用服务业务层是否存在性能瓶颈
    • Java 编程问题
    • 读写数据瓶颈等等

解决系统性能问题则可以采用自上而下的方式逐级优化:

2.1 优化代码

应用层问题代码往往会因为耗尽系统资源而暴露出来。

  • 如,某段代码导致内存溢出,往往是将JVM 中的内存用完了,这时系统内存资源消耗殆尽,同时也会引发JVM 频繁地发生垃圾回收,导致 CPU 100% 以上居高不下,这时又消耗了系统的CPU资源

非问题代码导致的性能问题比较难发现,需要依靠经验

  • 例如,LinkedList集合使用for循环遍历,将大大降低读的效率,但这种降低很难导致系统性能参数异常。应该使用 Iterator 迭代器循环集合(因为链表)

    2.2 优化设计

    面向对象的设计模式。优化后不仅精简代码,还能提高整体性能

    2.3 优化算法

    不同场景,使用合适的查找算法可降低时间复杂度

    2.4 时间换空间

    对查询速度没有很高要求,反而存储空间要求苛刻

    2.5 空间换时间

    使用存储空间来提升访问速度,如MySQL 的索引

    2.6 参数调优

    根据业务场景,合理地设置 JVM 的内存空间以及垃圾回收算法可提升系统性能。
    如,如果业务中创建大量的大对象,可通过设置,将大对象直接放进老年代,减少年轻代频繁发生小的垃圾回收,减少 CPU 占用,提升性能。
    Web 容器线程池的设置以及Linux 系统的内核参数设置不合理也有可能导致系统性能瓶颈,根据自己的业务优化。

    3. 兜底策略,确保系统稳定性

    以上为提高系统性能手段,但无论系统优化得多好,还会存在承受极限,所以为了保证稳定,还需要采用一些兜底策略。

    3.1 什么是兜底策略

  • 限流,对系统的入口设置最大访问限制。这里参考 TPS。同时采取熔断措施,友好地返回没有成功的请求。

  • 实现智能化横向扩容。可以保证当访问量超过某一个阈值时,系统根据需求自动横向新增服务
  • 提前扩容。常用于高并发系统,如抢购业务,因为横向扩容无法满足大量瞬间请求,即使成功了,抢购也结束了

    小结

    02 如何制定性能调优策略 - 图1
    注意:任何调优都需要结合场景明确已知问题和性能目标,不能为了调优而调优,以免引入新的BUG,带来风险和弊端。