高流量场景下Node.js实时通知服务性能优化方案咨询
实时通知服务性能优化方案与思路
一、先拆架构:API和Socket.IO服务分家
- 把Express API和Socket.IO服务器部署到不同的服务器实例上,别让API的CPU/IO消耗抢占Socket.IO的长连接资源。单台4核8G同时扛API和10万+长连接,资源肯定不够用。Socket.IO的长连接本身会占内存和文件描述符,分开后可以针对性给Socket.IO节点扩容。
二、Socket.IO集群化+负载均衡
- 用Socket.IO的Redis Adapter实现多节点间的消息同步,这样就能横向加Socket.IO服务器节点了。负载均衡可以用Nginx或者HAProxy,注意握手阶段要开会话粘性(不然握手会失败),等连接建立成WebSocket后,粘性就不是必须的了。
- 调Socket.IO的配置:只保留
websocket传输方式,关掉polling,减少握手阶段的开销;设置合理的pingTimeout(比如30秒)和pingInterval(比如25秒),及时清理无效连接,释放资源。
三、MongoDB针对性优化
- 加复合索引:针对用户查未读通知、按时间排序这类高频查询,建
{userId: 1, isRead: 1, createdAt: -1}这种复合索引,避免全表扫描拖慢速度。 - 读写分离:把通知写入(发通知)和读取(拉通知)分到MongoDB的主从节点,减轻主库压力。
- 批量操作:批量发通知时用
bulkWrite代替多次单条插入,减少数据库请求次数。 - 加Redis缓存:缓存用户的未读通知数、最近几条通知,用户打开页面先查缓存,再异步把MongoDB的数据同步到缓存,减少MongoDB的查询量。
四、服务器和Node.js参数调优
- Node.js参数:启动时加
--max-old-space-size=6144(给Node.js分配6G内存,留2G给系统和其他服务);如果有CPU密集型任务(比如通知内容过滤、格式化),用Worker Threads处理,别阻塞Event Loop。 - 系统层面:调大文件描述符限制(
ulimit -n 65535),每个Socket连接都占一个描述符,10万连接必须够;开启TCP参数tcp_tw_reuse和tcp_tw_recycle,减少TIME_WAIT状态的连接占用。
五、业务逻辑砍冗余
- 通知分级:实时性高的(比如@提醒)用Socket.IO推,非实时的(比如系统公告)批量定时推,减少Socket.IO的消息量。
- 离线消息处理:用户离线时把消息存到MongoDB或者Redis List,上线后批量拉取,别重复推送。
- 客户端去重:用户当前页面已经显示的内容,别再推一遍,客户端做个消息ID去重逻辑。
内容的提问来源于stack exchange,提问作者Abdelkader Bouzomita
相关产品推荐
相关产品推荐

