程序员必备的十大技能(进阶版)之性能调优与故障排查(四)

简介: 教程来源 https://aescc.cn/ 本节系统介绍Java应用性能分析与稳定性保障核心实践:涵盖Arthas诊断、火焰图性能剖析、全链路压测方法论及JMeter实战、混沌工程故障注入(ChaosBlade),并复盘Full GC与数据库死锁两大典型故障案例,助力高效定位与解决线上性能问题。

七、应用性能分析工具

7.1 Java诊断工具全家桶

# Arthas(阿里开源,必学)
# 官方:https://arthas.aliyun.com

# 快速入门
java -jar arthas-boot.jar
# 选择Java进程

# 常用命令
dashboard          # 实时面板(CPU、内存、线程)
thread             # 查看线程
thread -n 5        # 查看最繁忙的5个线程
jvm                # 查看JVM信息
sysprop            # 查看系统属性
sysenv             # 查看环境变量

# 方法监控
watch com.example.service.OrderService findById '{params,returnObj,throwExp}' -x 2
# 参数说明:{params}参数, {returnObj}返回值, {throwExp}异常

# 方法执行耗时
trace com.example.service.OrderService findById -n 5

# 方法调用统计
monitor -c 5 com.example.service.OrderService findById

# 热更新代码
jad com.example.service.OrderService        # 反编译
mc -c 327a647b /tmp/OrderService.java      # 编译
redefine /tmp/com/example/service/OrderService.class  # 热更新

# 火焰图
profiler start
profiler stop --format html

7.2 火焰图分析

# 生成CPU火焰图
# 使用perf生成
perf record -F 99 -p <PID> -g -- sleep 60
perf script > out.perf
# 使用FlameGraph工具生成
stackcollapse-perf.pl out.perf > out.folded
flamegraph.pl out.folded > cpu-flamegraph.svg

# 使用async-profiler(推荐)
./profiler.sh -d 60 -f /tmp/flamegraph.html <PID>

火焰图解读:

X轴:采样数量(宽度越大,CPU占用越高)

Y轴:调用栈深度

颜色:随机,无特殊含义

山顶平顶:说明CPU在此函数中执行时间较长

宽度突变:说明该分支是热点路径

7.3 阿里Java诊断工具Arthas深度使用

// 场景1:定位慢方法
// 使用trace跟踪方法调用链
trace com.example.service.OrderService findById

// 输出示例:
// +--[1.234s] com.example.service.OrderService:findById()
//     +--[0.001ms] com.example.dao.OrderMapper:selectById()
//     +--[1.200s] com.example.service.InventoryService:checkStock()
//     |   +--[1.190s] com.example.client.InventoryClient:callRemote()
//     +--[0.023ms] com.example.dao.OrderMapper:updateStatus()

// 场景2:监控接口QPS和响应时间
monitor -c 5 com.example.controller.OrderController *

// 场景3:查看方法参数和返回值(线上调试)
watch com.example.service.OrderService createOrder '{params[0], returnObj}' -x 3

// 场景4:定位ClassLoader问题
sc -d com.example.service.OrderService

// 场景5:查看Spring容器中的Bean
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod

7.4 性能剖析工具对比
image.png

八、全链路压测

8.1 压测方法论

压测类型:
  - 基准测试: 单机单接口基线
  - 负载测试: 逐步加压至预期目标
  - 压力测试: 寻找系统拐点
  - 稳定性测试: 长时间运行验证
  - 峰值测试: 模拟突发流量
  - 容量规划: 确定资源与吞吐量关系

压测流程:
  1. 明确目标: 预期QPS、响应时间
  2. 准备数据: 脱敏生产数据、构造测试数据
  3. 环境隔离: 独立压测环境或流量染色
  4. 脚本开发: JMeter/Gatling脚本
  5. 执行压测: 从低到高逐步加压
  6. 监控分析: 实时观察系统指标
  7. 瓶颈定位: 找到性能拐点
  8. 优化迭代: 针对性优化

8.2 JMeter压测脚本示例

// JMeter BeanShell预处理脚本
import java.util.UUID;

// 生成唯一订单ID
vars.put("orderId", UUID.randomUUID().toString());

// 生成随机用户ID
vars.put("userId", String.valueOf(ThreadLocalRandom.current().nextInt(1, 100000)));

// 生成测试数据
String json = "{\"userId\":\"" + vars.get("userId") + 
              "\",\"orderId\":\"" + vars.get("orderId") + 
              "\",\"amount\":" + ThreadLocalRandom.current().nextInt(100, 10000) + "}";
vars.put("requestBody", json);

8.3 压测结果分析

# JMeter聚合报告关键指标
# Samples: 请求数
# Average: 平均响应时间
# Min: 最小响应时间
# Max: 最大响应时间
# Std. Dev: 标准差(波动越大性能越不稳定)
# Error %: 错误率(应<0.01%)
# Throughput: 吞吐量(QPS/TPS)

# 性能拐点判断
# 当响应时间随着并发数增加出现非线性增长时,说明达到瓶颈
# 常见拐点:CPU>80%、GC频繁、连接池满、数据库连接池满

九、混沌工程

混沌工程通过主动注入故障,验证系统的韧性。

9.1 故障注入工具

ChaosBlade(阿里开源):
  安装: curl -L -O https://github.com/chaosblade-io/chaosblade/releases/download/v1.7.2/chaosblade-1.7.2-linux-amd64.tar.gz

  CPU满载: blade create cpu load --cpu-percent 80
  CPU释放: blade destroy <UID>

  内存占用: blade create mem load --mem-percent 80
  内存释放: blade destroy <UID>

  网络延迟: blade create network delay --time 3000 --offset 1000 --interface eth0
  网络丢包: blade create network loss --percent 30 --interface eth0

  磁盘IO: blade create disk fill --path /tmp --size 1024
  Java异常: blade create jvm throwCustomException --classname com.example.service --methodname getUser

9.2 混沌实验设计

实验场景:
  基础设施故障:
    - 宕机: 随机kill一个节点
    - 网络分区: 隔离部分节点
    - 时钟偏移: NTP不同步

  应用层故障:
    - 慢响应: 增加方法延迟
    - 异常抛出: 随机抛出业务异常
    - 依赖不可用: 关闭外部服务

  资源耗尽:
    - CPU满负载
    - 内存OOM
    - 磁盘写满

验收标准:
  - 故障恢复时间 < 5分钟
  - 错误率 < 1%
  - 无数据丢失
  - 熔断降级生效

十、经典故障案例复盘

10.1 案例一:Full GC频繁导致服务不可用
现象:

服务每30秒发生一次Full GC,每次停顿3-5秒

请求超时率上升,RT从50ms飙升到10秒

排查过程:

# 1. 查看GC日志
jstat -gcutil <PID> 1000

# 输出:
# S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
# 0.00  98.22  85.33  99.98  95.12  91.23   1250    15.23   150    450.32  465.55

# 老年代占用99.98%,频繁Full GC

# 2. 查看堆内存对象分布
jmap -histo:live <PID> | head -20

# 发现:
# 1: 0x00000006c0a8a0a0 30000000  1200000000  [C
# 2: 0x00000007c0b8b0b0 25000000  1000000000  java.lang.String

# 3. dump堆内存分析
jmap -dump:live,format=b,file=heap.hprof <PID>

# MAT分析发现大量String对象未被释放

根因:

// 问题代码:日志打印了大对象
public void processLargeData() {
    String largeData = readLargeFile(); // 100MB数据
    // 生产环境日志级别是INFO,但对象已经创建
    log.debug("Processing data: {}", largeData);
}

// 解决方案
public void processLargeData() {
    if (log.isDebugEnabled()) {
        String largeData = readLargeFile();
        log.debug("Processing data: {}", largeData);
    }
}

10.2 案例二:数据库死锁导致订单服务不可用
现象:

订单创建成功率从99.99%下降到80%

数据库CPU飙升到100%

排查过程:

-- 1. 查看死锁信息
SHOW ENGINE INNODB STATUS\G

-- 死锁日志:
-- *** (1) TRANSACTION:
-- TRANSACTION 12345, ACTIVE 2 sec starting index read
-- mysql tables in use 1, locked 1
-- LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
-- UPDATE orders SET status = 'PAID' WHERE id = 1001
-- 
-- *** (2) TRANSACTION:
-- TRANSACTION 12346, ACTIVE 2 sec updating or deleting
-- mysql tables in use 1, locked 1
-- 3 lock struct(s), heap size 1136, 2 row lock(s)
-- UPDATE orders SET status = 'SHIPPED' WHERE id = 1001
-- 
-- *** WE ROLL BACK TRANSACTION (2)

-- 2. 分析事务隔离级别
SELECT @@transaction_isolation;
-- REPEATABLE-READ

-- 3. 查看索引使用情况
EXPLAIN UPDATE orders SET status = 'PAID' WHERE id = 1001
-- type: ALL(全表扫描!)

根因:

id字段没有索引,UPDATE操作锁全表

两个并发事务同时更新不同数据,但由于锁全表导致死锁

解决方案:

-- 1. 创建索引
ALTER TABLE orders ADD INDEX idx_id (id);

-- 2. 优化事务范围
-- 事务中只保留必要的操作,减少持锁时间

-- 3. 使用乐观锁
ALTER TABLE orders ADD COLUMN version INT DEFAULT 0;

UPDATE orders 
SET status = 'PAID', version = version + 1 
WHERE id = 1001 AND version = 1;

来源:
https://vrhyh.cn/

相关文章
|
27天前
|
缓存 安全 Windows
电脑开关机、运行卡顿! 科学清理 C 盘释放存储空间实用妙招!
电脑C盘爆红、卡顿、软件闪退?本文提供一套安全、高效、可长期维护的C盘清理流程,从基础清理到系统优化,再到专业工具深度处理,新手也能轻松上手,一次性释放大量空间,让电脑重回流畅状态
|
27天前
|
监控 Java 测试技术
Java 软件测试(二):Mockito与JUnit 5应用
Java 软件测试(二):Mockito与JUnit 5应用
83 0
|
27天前
|
PyTorch API 调度
在 AMD ROCm DSW 上跑通 DeepSeek-V4-Flash:vLLM 兼容部署、长上下文验证与 8K 性能扫参
本文记录一次在 ModelScope DSW AMD GPU/ROCm 环境中部署 DeepSeek-V4-Flash 的工程实践:通过 vLLM、ROCm/AITER/PyTorch fallback 与兼容补丁建立可复现 baseline,并用短问答、2K/8K/32K needle retrieval 和 8K top-k 扫参验证正确性与性能边界。
638 1
在 AMD ROCm DSW 上跑通 DeepSeek-V4-Flash:vLLM 兼容部署、长上下文验证与 8K 性能扫参
|
27天前
|
Prometheus 监控 Cloud Native
MySQL 性能监控实战:从零搭建 Prometheus + Grafana 监控告警体系(附排查 SOP)
数据库小学妹带你从零学监控!本文详解MySQL五大核心指标维度(资源、连接、查询、InnoDB、主从),手把手配置PMM/Prometheus+Grafana监控栈,设置关键告警规则,并提供SQL快照脚本与三步排障SOP。新手友好,即装即用,让性能问题无所遁形!
|
27天前
|
Linux KVM 虚拟化
虚拟机使用教程大全(二)
教程来源 https://oplhc.cn/ 虚拟机网络模式深度解析:NAT(共享上网)、桥接(独立局域网身份)、仅主机(宿主隔离通信)、内部网络(纯虚拟机互通)及VMware自定义模式,涵盖原理、配置、端口转发与高级应用,助你精准构建安全高效实验环境。
|
25天前
|
SQL 安全 算法
软件开发进阶技能之性能与安全调优(四)
本节聚焦安全调优:严守最小权限原则,缩减攻击面。涵盖SQL注入(禁用拼接,用PreparedStatement/MyBatis #{})、XSS(输出编码+框架自动转义)、命令注入(白名单校验);JWT安全(强密钥、合理过期、防算法混淆);会话固定防护与bcrypt加盐哈希密码存储。
|
27天前
|
数据采集 运维 监控
【剪映小助手】数据转换工具接口
本数据转换工具提供3个核心API:字符串↔对象列表互转、字符串→单元素数组,基于Pydantic模型与分层架构(路由/服务/模型/中间件),支持自动校验、统一异常处理、结构化日志及性能优化,兼顾简洁性与生产级可靠性。(239字)
|
27天前
|
C#
base的使用(一)
c# base的使用(一)
|
27天前
|
Java 测试技术 BI
Java 软件测试(三):Mockito打桩与静态方法模拟解析
Java 软件测试(三):Mockito打桩与静态方法模拟解析
138 0
|
27天前
|
运维 监控 程序员
程序员必备的十大技能(进阶版)之性能调优与故障排查(三)
教程来源 https://bgnno.cn/ 本节系统讲解网络与数据库性能问题排查:涵盖TCP连接状态分析、TIME_WAIT优化、延迟诊断、连接池配置;以及慢查询定位、索引失效识别、事务锁监控和连接池调优,助力高效定位并解决生产环境常见瓶颈。