一、调优目标
性能调优首先需要明确目标,性能调优目标一般由3部分组成:
- 调优对象
- 调优范围
- 调优指标
比如“降低Go进程的总体内存占用”,“降低Java进程某个偶发个例的RT”。
1.1、调优对象
比如:
- 分布式系统
- Java进程
- Go进程
- Rust进程
- Linux系统
1.2、调优范围
分为两种:
- 总体,比如“总体TPS”
- 个体数据点,比如“一个请求的RT”
1.3、调优指标
有常见的调优指标,也有自定义的调优指标。
比如:
- 降低CPU
- 降低磁盘IO
- 降低网络IO
- 降低内存
- 降低RT
- 减少内部超时数和外部超时数
- 提升系统可用率
- 降低对MySQL的读写负载
- 降低对Redis的读写负载
- 降低对Dubbo服务的调用负载
二、具体手段
具体手段分为两步:先“定位”,再“优化”。
2.1、定位
定位是性能调优的核心环节。
定位可分为3类:“事前”、“事中”和“事后”。关于这3者的描述见表1。
表1
定位类别 | 步骤 | 使用工具/组件 | 特点 |
---|---|---|---|
事前 | 预先进行日志埋点 | 除了“自实现埋点”之外可使用APM组件埋点。埋点位置跟“具体调优指标”和“调优经验”有关 | 必能进行“事前”定位,灵活性差,因为只能记录预埋点相关日志 |
事中 | 保存现场信息,使用工具进行分析 | 使用工具进行分析,比如“对于Java进程,使用‘jstat’,‘jstack’,‘jmap+CAT’等工具进行分析” | 一些性能调优场景不能进行“事中”定位;在能进行“事中”定位的性能调优场景中,“事中”定位,灵活性稍好,因为可使用工具灵活自由分析 |
事后 | 使用测试数据进行回放,在回放前可自定义埋点,可进行单步调试,可使用工具进行分析 | 使用工具进行分析,比如“对于Java进程,使用‘jstat’,‘jstack’,‘jmap+CAT’等工具进行分析” | 一些性能调优场景不能进行“事后”定位;在能进行“事后”定位的性能调优场景中,“事后”定位,灵活性最好,因为可回放,自定义埋点,使用工具灵活自由分析,单步调试 |
总结来说:
- 进行定位需要有大局观,即`调优对象本身及所在环境都有可能影响调优指标,比如“在调优Java进程的RT时,Java进程本身、CPU、内存、IO、操作系统配置等都有可能影响RT”
- 对于“现场信息记录能力”,跟具体性能调优场景有关,比如“在小型简单系统中,3类定位也许都能够获取最完整的现场信息,而在大型复杂系统中,3类定位中可能只有“事后”定位能够最完整记录现场信息”
- 总结来看,“事前”、“事中”和“事后”定位能力没有强弱之分,各有所适应的性能调优场景,综合使用最佳。但是也如上所述,在大型复杂的系统中,“事前”定位一般必不可少
备注:
- APM组件,即“应用性能管理组件”,APM的英文全称为“Application Performance Management”。常见的APM组件有“Pinpoint”,“Zipkin”,“CAT”等
2.2、优化
一般有两种方案:
- 优化设计
- 优化算法和数据结构
三、事前定位 vs 监控报警
“事前”定位是为了揭露问题的原因所在。
“传统的监控报警”是为了告警问题的存在,并不侧重于揭示问题的原因所在。
而我们在接收到报警之后,自然而然地期望能够快速定位到问题的原因所在,这就导致了“APM组件”和“监控报警组件”之间的界限越来越模糊,“APM组件”和“监控报警组件”大有合流之势。
四、性能调优 vs 性能测试
“性能调优”和“性能测试(比如使用‘JMeter’工具)”的异同点在于:“性能调优”在上线之后,而“性能测试”在上线之前进行;但是两者的“调优目标”和“具体手段”完全一致。