2026年4月2日我们团队在准备一场大规模即时通讯系统的压力测试。目标是在50万在线用户、峰值每秒10万条消息的场景下保证99.9%的消息延迟不超过500ms。压测初期系统表现良好但随着并发量逼近8万监控大盘开始报警线程池满、消息堆积、推送延迟飙升至5秒以上。我们迅速介入排查发现核心瓶颈出现在消息推送模块的线程池配置上。以下是我们从现象到根因再到最终落地的完整复盘过程。一、业务目标高并发消息推送的稳定性保障即时通讯系统的核心能力之一是消息的实时推送。在高并发场景下用户发送消息后系统需要在毫秒级内将消息推送给接收方。本次压测的目标是验证系统在极端负载下的推送能力确保用户体验不受影响。技术约束包括推送延迟 ≤ 500msP99消息丢失率 ≤ 0.01%系统资源占用可控CPU ≤ 70%内存 ≤ 80%二、方案对比同步阻塞 vs 异步解耦在压测前消息推送模块采用同步阻塞模式核心代码如下public void pushMessage(Message message) { ExecutorService pushExecutor Executors.newFixedThreadPool(200); pushExecutor.submit(() - { try { // 模拟推送逻辑网络调用 数据库写入 Thread.sleep(100); // 模拟网络延迟 messageService.saveToDB(message); websocketService.sendToClient(message.getReceiverId(), message); } catch (Exception e) { log.error(推送失败, e); } }); }此方案的直观问题是线程池大小固定为200无法动态扩容每个推送任务都独立提交缺乏背压机制线程池满后新任务被拒绝导致消息堆积我们对比了三种优化方案| 方案 | 优点 | 缺点 | 适用场景 | |------|------|------|----------| | 增大线程池 | 实现简单快速缓解 | 资源消耗大无法根本解决阻塞 | 临时应急 | | 引入消息队列异步解耦 | 削峰填谷提升吞吐量 | 增加系统复杂度延迟略增 | 高并发场景 | | 使用Netty异步非阻塞推送 | 高并发低延迟资源利用率高 | 开发成本高需重构推送层 | 长期优化 |最终我们选择引入消息队列 异步解耦作为短期落地方案同时启动Netty改造作为长期规划。三、最终落地基于RocketMQ的异步推送架构我们重构了推送流程将同步推送改为异步处理// 改造后消息写入MQ由消费者异步处理 public void pushMessage(Message message) { // 快速写入MQ不阻塞主流程 rocketMQTemplate.asyncSend(push-topic, message, new SendCallback() { Override public void onSuccess(SendResult result) { // 可选记录发送成功日志 } Override public void onException(Throwable e) { log.error(消息写入MQ失败, e); // 降级策略写入本地文件定时重试 } }); } // 消费者端异步处理推送 RocketMQMessageListener(topic push-topic, consumerGroup push-group) public class PushConsumer implements RocketMQListenerMessage { Autowired private MessageService messageService; Autowired private WebsocketService websocketService; Override public void onMessage(Message message) { try { messageService.saveToDB(message); websocketService.sendToClient(message.getReceiverId(), message); } catch (Exception e) { log.error(推送处理失败消息ID: {}, message.getId(), e); // 重试机制MQ自动重试3次失败后进入死信队列 } } }关键优化点解耦推送与存储主流程只负责写入MQ不等待推送完成引入背压机制MQ天然具备流量控制能力避免线程池满提升吞吐量消费者可水平扩展处理能力随实例数线性增长增强可靠性MQ提供持久化、重试、死信队列等机制压测结果显示推送延迟从5秒降至200msP99系统CPU使用率从95%降至60%消息堆积问题彻底解决四、风险边界异步化带来的新挑战虽然异步化显著提升了性能但也引入了新的风险消息顺序性MQ分区内有序但跨分区可能乱序。我们通过在消息Key中嵌入会话ID确保同一会话的消息进入同一分区。最终一致性消息写入MQ后即返回成功但实际推送可能延迟。我们增加了消息状态追踪机制客户端可查询推送状态。死信队列处理推送失败的消息会进入死信队列需定期人工干预或自动修复。我们开发了死信监控面板支持一键重试。资源隔离推送消费者与业务逻辑消费者共享MQ集群可能造成资源竞争。我们通过独立Topic和Consumer Group实现逻辑隔离。五、技术补丁包线程池配置陷阱原理固定大小线程池在高并发下易满导致任务拒绝 设计动机简单直观适合低并发场景 边界条件任务执行时间长、突发流量大时失效 落地建议使用有界队列拒绝策略或改用异步非阻塞模型消息队列异步解耦原理通过MQ实现生产消费解耦削峰填谷 设计动机提升系统吞吐量和稳定性 边界条件增加系统复杂度延迟略有上升 落地建议选择高可用MQ如RocketMQ合理设置重试和死信策略Netty异步推送原理基于事件驱动的非阻塞IO支持高并发连接 设计动机极致性能适合IM、游戏等实时场景 边界条件开发维护成本高需深入理解网络编程 落地建议结合业务规模评估中小系统可优先MQ方案消息顺序性保障原理通过消息Key路由到同一分区保证分区内有序 设计动机满足IM会话内消息顺序要求 边界条件分区数固定扩展性受限 落地建议Key设计需包含会话ID避免热点分区最终一致性处理原理异步操作导致状态延迟需额外机制追踪 设计动机提升用户体验避免“消息已发未达”困惑 边界条件增加状态管理复杂度 落地建议提供消息状态查询API结合客户端轮询或WebSocket通知本次压测复盘让我们深刻认识到性能优化不仅是参数调优更是架构思维的体现。从同步阻塞到异步解耦不仅是技术栈的升级更是对系统边界和风险认知的深化。