凌晨两点的告警电话,大促压测TP99直接飙到2.3秒,团队第一反应是查数据库,结果DBA翻了半天慢日志,发现数据库CPU只有12%——问题根本不在数据层。这是我在高并发系统性能优化实战中印象最深的一次。高并发系统性能优化是个听着很宽泛、做起来特别容易跑偏的领域,大多数人的第一反应是加机器、加Redis、上分库分表,结果往往是在错误的方向上疯狂堆成本。这篇内容立足我多年一线调优经验,讲清楚优化的真正起点、分层手段和那些很少有人写在文档里的坑,适合后端开发、架构师以及对高并发调优感兴趣的读者。你不需要一上来就背一堆参数,先掌握一套定位瓶颈的方法论,比学会一百个优化技巧都管用。
1. 先搞清楚你的系统到底卡在哪:瓶颈定位方法论
1.1 一次凌晨告警教我的事
先说个真实经历。之前带过一个电商交易链路,大促压测时接口TP99从平时的80ms直接飙到2.3s,告警半夜把我从床上拉起来。当时团队第一反应是数据库扛不住了,DBA翻慢日志翻了半天,发现数据库CPU只有12%,磁盘IO也没到瓶颈,虽然是有一批慢SQL,但每一条都是走主键的单行查询,怎么看都不像主因。最后用链路追踪一抓,问题居然出在网关层的JSON序列化——订单对象嵌套了十几层,字段多不说,里面还塞了几个巨大的list,每个请求进来要反序列化一次、转发出去再序列化一次,几百MB的请求体就这么被反复处理,GC压力也跟着飙上去。
这个案例让我一直记到现在。高并发系统性能优化的难点,往往不是"怎么优化",而是"往哪儿优化"。在错误的方向上优化,做得越深,浪费越大。从那以后,我给自己定了一条规矩:线上性能问题,没有全链路数据之前不许动代码。
1.2 性能瓶颈通常藏在四个位置
从我接触到的大量线上问题来看,高并发系统的性能瓶颈基本逃不出下面这四个位置:
| 瓶颈位置 | 典型表现 | 初步排查手段 |
|---|---|---|
| 网络链路 | 请求延迟波动大、跨机房RTT高、丢包重传 | ping、mtr、网关层耗时统计 |
| 接入/网关层 | 连接数打满、线程池拒绝、序列化耗时高 | 网关访问日志、线程池监控、profiler |
| 应用服务层 | CPU飙高、GC频繁、线程阻塞、内存溢出 | top、jstack、heap dump、火焰图 |
| 缓存与数据层 | 缓存命中率低、慢SQL、连接池耗尽、锁等待 | 缓存监控、慢日志、EXPLAIN、DB监控 |
很多人一遇到性能问题就去查数据库,是因为数据库最"显眼"。但实际经验告诉我,很多系统的瓶颈其实在更靠前的位置。我一般会先看整条链路的耗时分布——请求从进网关到应用、到缓存、到数据库,每个环节各花了多少时间。哪个环节耗时异常,就往哪里深挖。比如响应时间1秒,应用层只花了50ms,数据库只花了30ms,那问题八成在网络或客户端;反过来,如果应用层就占了900ms,那应该立刻去应用线程栈里看卡在哪个调用上。
1.3 用数据说话:链路追踪与压测的基本姿势
定位瓶颈光靠猜不行,必须有全局数据。我现在处理高并发问题的标准配置是:SkyWalking或者Zipkin做全链路追踪,每个请求生成一个traceId,从头到尾记录每一步耗时;Prometheus加Grafana做指标监控;压测用wrk或者JMeter做基础压力测试,必要时配合全链路压测平台做容量验证。
一个traceId贯穿网关、应用、缓存、数据库的调用链,一旦哪个环节耗时长,十分钟之内就能看到。这套东西不是高深技术,但在很多团队里真的很稀缺——大家习惯"感觉是这里慢"就去这里翻,翻了半天没结果。我处理问题从来是先在监控面板上把链路耗时分布截出来,拿数据说话,再决定往哪个方向使劲。没有这个习惯的人,往往会在定位阶段浪费掉整个优化项目一半的时间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 应用层优化:线程模型、连接池与异步化的取舍
2.1 线程数不是越大越好:从Tomcat参数说起
很多刚接触高并发的同学有个根深蒂固的误区:线程池越大,并发处理能力
