Java经典面试解析:服务器卡顿、CPU飙升、接口负载剧增(实战必看!!!)
(图注:服务器性能问题三连击 - 每个开发者都逃不过的噩梦!)
一、服务器卡顿:突然变慢为哪般?
1.1 现象特征
- 请求响应时间从200ms飙升到5s+
- 服务器监控面板"全屏飘红"(CPU、内存、磁盘三高)
- 日志中频繁出现Connection timed out警告
1.2 排查三板斧
第一斧:top命令看全局
bash
top -H -p <PID> # (超级重要)一定要加-H显示线程信息!!!
重点关注:
- %CPU > 300% 的线程(可能是死循环)
- WAIT状态的线程数(I/O阻塞预警)
第二斧:jstack抓线程快照
java
jstack -l <PID> > thread_dump.log
快速定位技巧:
1. 把线程ID转成16进制(printf "%x\n" 21742)
2. 在dump文件搜索nid=0x54ee
第三斧:jstat看GC情况
bash
jstat -gcutil <PID> 1000 # 每秒打印一次GC数据
关键指标:
- FGC > 5次/分钟(Full GC太频繁!)
- OU超过90%(老年代要溢出了)
1.3 实战案例
某电商系统凌晨突然卡顿,通过jstack发现:
java
"Thread-15" #32 prio=5 os_prio=0 tid=0x00007f48740d5000 nid=0x54ee runnable [0x00007f486b7ec000]
java.lang.Thread.State: RUNNABLE
at java.util.HashMap.putVal(HashMap.java:634)
at java.util.HashMap.put(HashMap.java:611)
at com.example.CacheManager.addToLocalCache(CacheManager.java:127)
(破案了!)本地缓存没有设置过期时间,HashMap无限膨胀导致OOM前兆!
二、CPU 100%飙车现场
2.1 经典死循环代码
java
// 错误示例(千万别学!)
while(true) {
// 没有break条件!!
processData();
}
2.2 高级排查技巧
神器Arthas出场:
```bash
1. 启动arthas
java -jar arthas-boot.jar
2. 监控最忙线程
thread -n 3
3. 方法执行监控
watch com.example.Service * '{params,returnObj}' -x 3
```
2.3 意想不到的坑
- 正则表达式灾难:String.matches("(a+)+")处理长字符串
- 序列化/反序列化:Jackson解析多层嵌套JSON
- 数学计算:BigDecimal.divide()未指定精度模式
(血泪教训)某金融系统CPU突然100%,最终发现是证书验证时的BCrypt.checkpw方法被频繁调用!
三、接口负载暴增:从崩溃到优雅
3.1 限流方案对比
| 方案 | 优点 | 缺点 |
|--------------|----------------------|-----------------------|
| 令牌桶 | 平滑突发流量 | 实现稍复杂 |
| 漏桶 | 绝对速率控制 | 响应延迟增加 |
| Sentinel | 整合Spring Cloud | 需要额外依赖 |
| Resilience4j | 功能全面 | 学习曲线陡峭 |
3.2 代码级优化技巧
缓存穿透解决方案:
```java
// 布隆过滤器伪代码
public class BloomFilter {
private BitSet bitset = new BitSet(DEFAULT_SIZE);
}
```
连接池配置(Tomcat版):
```properties
application.properties
server.tomcat.max-threads=200
server.tomcat.min-spare-threads=20
server.tomcat.accept-count=100
server.tomcat.connection-timeout=5000
```
3.3 架构级防御
- 服务降级:Hystrix fallback快速返回兜底数据
- 流量染色:区分正常流量和爬虫请求
- 弹性扩容:K8s HPA自动扩展Pod数量
(真实案例)某社交APP突发热点事件,通过提前设置的熔断规则,自动降级非核心功能,保住核心链路!
四、防患于未然:监控体系搭建
4.1 必备监控项
- 基础指标:CPU/Memory/Disk
- JVM监控:GC次数/内存池使用率
- 业务指标:QPS/平均RT/错误率
4.2 Prometheus + Grafana配置示例
```yaml
prometheus.yml
scrape_configs:
- job_name: 'spring_app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
```
4.3 报警规则设置
```sql
钉钉报警规则示例
groups:
- name: critical-alert
rules:
- alert: HighErrorRate
expr: sum(rate(http_server_requests_seconds_count{status!~"2.."}[5m])) / sum(rate(http_server_requests_seconds_count[5m])) > 0.5
for: 2m
annotations:
summary: "高错误率报警"
description: "当前错误率已达{{ $value }}!"
```
五、终极解决方案:从灭火到防火
- 混沌工程:定期进行故障演练(比如拔网线、杀进程)
- 压测常态化:每周执行全链路压测
- 代码审查:重点检查资源关闭操作(Connection/Stream必须finally!)
- 技术债务看板:技术债可视化,限期偿还
(最后的大招)建立容量规划模型:
所需机器数 = (总QPS × 平均RT) / (单机线程数 × 目标利用率)
总结与思考
通过这三个经典问题的深度解析,我们可以总结出性能优化的黄金法则:
- 监控先行:没有度量就没有优化
- 分层排查:从全局到局部,从现象到代码
- 防御性设计:把故障当作必然发生的事件来预防
最后送大家一句口诀(建议贴在显示器上):
"早压测、早限流,监控报警不能丢;线程池、连接数,配置不当要吃苦!"
遇到问题不要慌,按照本文的排查路线图一步步来,你也能成为团队里的"救火英雄"!如果觉得有用,赶紧收藏转发,说不定明天就用上了呢?(眨眼)
浙公网安备 33010602011771号