服务器被压测时,系统稳不崩溃的关键不是堆硬件,而是提前设计好限流、熔断、降级、扩容四件套,并在压测前完成真实流量级的容量摸底,没有预案的压测,崩只是时间问题。
服务器压测崩溃怎么办?先搞清楚压力打在哪一层
很多团队的压测现场是这样的:并发数一上来,监控面板全线飙红,机房报警响成一片,运维手忙脚乱加机器,结果加了机器照样崩,为什么?因为压力根本没有打到那台新增的机器上,而是卡在某个你没想到的连接瓶颈上。
压测崩溃的第一反应不应该是扩容,而是定位瓶颈层,常见的瓶颈分布在这四层:
- 网络层:带宽被打满,或者TIME_WAIT连接堆积导致新连接无法建立
- 应用层:进程线程数耗尽,GC频繁触发,锁竞争激烈
- 数据库层:连接池被打穿,慢查询拖垮主库
- 缓存层:缓存穿透击穿雪崩,回源压力直接打到数据库
判断方法不靠猜,靠命令,压测时开三个终端,分别盯着top、vmstat 1和ss -s,如果ss -s显示TIME_WAIT连接数过万,问题在连接层;如果top里CPU的si指标偏高,说明在争抢内存;如果数据库侧show processlist里出现大量未提交事务,那瓶颈在SQL复杂度上。
行业共识认为,绝大多数压测崩溃不是硬件不够,而是连接管理和资源池参数不合理,比如默认的连接池配置是按照日常流量设计的,压测流量十倍百倍往上冲时,池子先被抽干,应用层还在拼命创建新连接,最终雪崩,这一步的解决原则是:先压缩单机无效开销,再谈水平扩展。
高并发服务器怎么配置才能扛住压测
如果你已经确认瓶颈在自己管得到的代码和配置层面,接下来按这四层逐项加固。
连接层:内核参数和反向代理先调到位
最常见的是TIME_WAIT和文件句柄限制,压测前把这两个内核参数改掉,能少崩溃一半:
- 在
/etc/sysctl.conf里设置net.ipv4.tcp_fin_timeout = 10,缩短TIME_WAIT回收周期 - 调大
net.core.somaxconn = 2048,让高并发下socket队列能存更多待处理请求 - 把
fs.file-max和进程的ulimit -n同步调高到65535以上
反向代理层如果是Nginx,worker_connections要和业务QPS预估匹配,keepalive连接池数量也要同步调大,只调Nginx而不调内核参数,效果会大打折扣,很多团队压测崩溃就是栽在这里。
应用层:限流和熔断必须提前埋点
业内专家指出,压测时最考验的不是程序处理能力,而是流量突然涌来时系统有没有自我保护机制,在网关层加令牌桶限流,在微服务调用链里加熔断开关,这两项属于标配。
- 限流阈值不要拍脑袋,取压测摸底结果中单机稳定QPS的70%-80%
- 熔断器阈值设置为超时率超过20%持续10秒即触发降级
- 降级策略必须能捞回数据,比如降级到静态缓存时,要保证最终有补偿任务把数据补齐
如果你用的是Spring Cloud,Resilience4j的配置里有个failureRateThreshold参数,压测前把这个值设好,能直接避免服务间调用互相拖死,Java原生环境也可以用Guava RateLimiter,但要注意它默认是平滑突发限流,压测场景里的尖峰流量需要手工调预热期参数。
缓存层:热点数据必须打散,冷热分离要清楚
压测时最怕缓存穿透,用Redis做缓存时,压测前先确认是否开启了:
- 空值缓存(防止查询不存在的数据时每次打到DB)
- 布隆过滤器拦截非法key(业内常规做法,适合数据量可控的场景)
- 热点数据多副本分摊(比如把同一个key复制多份加后缀,分布在集群不同实例上)
压测过程中一旦发现Redis的get命中率掉到80%以下,优先检查有没有大key和热key,别急着加节点,加节点解决不了热key单点压力,反而可能让数据分片不均匀。
数据库层:连接池和慢查询是命门
数据库连接数不是越大越好,把max_connections调高往往适得其反,因为每个连接都要占内存和CPU调度资源。合理做法是压测前算出平均每个请求占用连接的时间,乘上预估QPS,再留20%余量,用这个公式去定连接池上限。
压测时SQL层面要提前开启慢查询日志,阈值设1秒就够,压测跑完第一轮立刻拉取慢日志,把排名前五的慢SQL优先优化掉,很多压测崩溃最后都查到一个全表扫描的SQL,加索引之后当场稳定。
服务器压测和性能测试的区别是什么
每次压测前,团队里总有人分不清这次到底算压力测试还是性能测试,导致目标定错,测出来的数据也没法指导生产配置,实际区别集中在三方面:
| 对比维度 | 压力测试 | 性能测试 |
|---|---|---|
| 核心目标 | 找到系统的崩溃点和极限值 | 验证系统能否达到预期性能指标 |
| 施压方式 | 持续加压直到系统出现异常 | 在预期负载范围内阶梯加压 |
| 关注指标 | 崩溃时的并发数、错误率、恢复时间 | P99延迟、吞吐量、资源利用率 |
| 结束条件 | 系统出现性能拐点或资源耗尽 | 指标达标即结束 |
压测崩溃处理要基于压力测试的结果去设计,性能测试告诉你系统“正常情况下能跑多快”,压力测试才告诉你系统的极限在哪、崩溃后能不能自己缓过来。
实际项目中,建议先跑一轮性能测试拿到基线数据,再递增并发做压力测试,压到系统开始报错、延迟飙升的那一刻,记录下当时的各项指标,这些数据就是后续容量规划和限流阈值的依据。
服务器扛不住压测怎么办?立刻能做的五件事
如果压测已经开始,系统显示扛不住的信号,别慌,按优先级顺序执行下面这些动作。
- 第一步:降级而非重启,重启服务会丢弃全部连接和内存数据,降级则只切断非核心链路,把推荐位、通知推送、日志上报等边缘功能直接关掉,释放出20%-30%的余量给核心交易链路。
- 第二步:限流阈值调低30%,如果你预设的是单机10000 QPS,直接压到7000,保证已有请求稳稳处理完,压测的目的本来就是看系统的波动表现,不是看极限数字多好看。
- 第三步:把读流量切到从库或缓存副本,备机横竖都要上,临时改读写分离,至少能坚持到压测结束。
- 第四步:检查GC日志和线程阻塞,如果JVM的Full GC超过每5分钟一次,说明堆内存快满了,立刻调低堆中的缓存大小,而不是加内存条。
- 第五步:摘掉异常节点,如果某台机器响应耗时是其他机器的三倍以上,直接摘掉服务,让负载均衡器把流量分配给健康的节点,留着它只会拖慢整个集群。
压测结束后,别急着收拾现场,把压测期间的监控数据导出来,标记出资源耗尽的时间点、错误日志的种类、恢复所用的时长,这些数据比压测报告更值钱,短信告警规则、容量评估、扩容计划都会以它们为依据。
再次压测时,只改一个变量,比如限流阈值改了就不动连接池配置,验证通过后再动下一个,一次优化多个参数,你根本不知道是哪个起了作用。
关于服务器压测与系统稳定的常见问题
压测到多少QPS算正常?需要撑住多久?
没有统一标准,取决于业务场景和机器规格,行业参考做法是:单台8核16G的机器,纯接口读取场景稳定支撑2000-3000QPS算合格,涉及复杂计算或多表查询则会降到500-800,撑住的时间建议不低于持续压测30分钟,短时间冲上去没参考价值,线上流量是持续存在的,系统必须在一个稳定水平上连续运行不出异常。
压测时数据库连接池被瞬间打满怎么办?
连接数被打满表明连接回收速度跟不上新建速度,先查是否有慢SQL占用连接,把超过2秒的查询抓出来优化,同时把连接池的maxLifetime适当缩短,让空闲连接更快回收,临时扩容手段是调大连接池上限20%-30%,但这只是缓兵之计,根源不除下次压测还会重演。
压测机器配置和生产环境不一致,测出来的数据有用吗?
有用,但需要换算,压测机的CPU性能和生产差多少倍,QPS结果就按比例折算,更要紧的是观察资源曲线形态,带宽和内存占用率的变化趋势不会因为机型不同而改变,小机器压测能暴露出来的问题,生产环境放大后问题依旧存在,只是表现时间点不同。