IM消息推送开发:从崩溃到千万级连接的逆袭之路

2026-05-01 0 732

标题想了半小时还是没想好。

算了。

反正大概就是这个意思。

上个月组里出了个大事故。

凌晨两点,值班的同事打来电话,声音都在抖。

说IM推送服务崩了。5w人连不上。线上炸了锅。

你知道吗,那一刻我突然想起三年前。

我第一次做推送模块的那天。

得意洋洋写了几百行代码,心想“不就发个消息嘛”。

这一回首次进行压测,当第2000个用户连接上来之际,程序一下子就出现 ,直接在原地失败了。

脸红得像煮熟的虾。

自那以后我再也不敢说推送简单。

到底什么是高性能推送

说白了就是两层。

第一层,连接

你得想办法让客户端和服务端之间那条绳子不断。

冲进地铁隧道,是不是断掉了?App程序被强制关闭了,是不是消失了?手机因为电量耗尽而自动关机了,是不是没辙了?

每一层都是坑。

我见过最蠢的方案——短轮询。

每隔几秒钟问一次服务器“有新消息吗?”

你想啊,就算没有新消息,客户端也在疯狂发请求。

服务器的CPU,被烤得出现冒烟的情况,而用户体验糟糕到了极点,延迟了好几秒,才收到反馈。

这不是推送,这是折磨。

王道乃长连接,为当下主流之选,其具全双工通道,于服务端而言,可随时主动推送数据。

但这只是第一步。

消息队列才是救命稻草

给你讲个真事儿。

去年压测,50w在线用户,峰值每秒10w条消息。

初期方案:固定线程池200个。

一开始还行,等并发冲到8w,砰——线程池满了。

消息堆积。延迟飙到5秒以上。监控大盘报警声此起彼伏。

那晚,我们三个人,蹲在会议室,那会议室,实际是线上的,可气氛,却好似机房那般。

改了一夜。

最后确定方案:异步+消息队列

将消息直接写入里,在该MQ顶上,主流程不会出现卡顿情况,由消费者缓慢进行推送操作,以此实现削峰填谷的效果。

改完再测,延迟稳定在200ms以内。爽。

实际上,其原理并非复杂万分,并非要在单一的路径之上,把所有事情都给堵塞住,而是应当依据实际情况,该进行卸货操作的,就去实施卸货,该稍作等待的,那就等待片刻。

Go还是Java?吵了三年还在吵

我给不了你标准答案。

维护海量长连接于接入层,Go原生有着GMP并发模型,单机能够把几十万并发连接支撑,确实是很香的。

但你让Go去写复杂业务逻辑试试?

啧。

所以现在的套路是:接入层Go,逻辑层Java或者PHP

各干各的。分工明确。

接口一对接,世界清净了。

有的人呀,时而会陷入想不明白的状况,非得借助一把锤子去敲击每一颗钉子,实际上更换一种工具并非是什么丢人的事情。

消息要是丢了怎么办

这个问题最让我头疼。

说白了,保证消息不丢就一招——不管发没发出去,都当没发过

直到收到ACK确认信号。

三层保险:

1. 客户端先存本地。只要是没收到ACK,死活不删。

2. 服务端获取到消息,随即撰写,同步进行复制,且复制至最少3个副本。

3. 进行定时扫描,针对待确认集合,若超时未回,便实施重发操作。通过幂等方式去除重复,以此防止出现重复情况。

好麻烦对吧。

但没办法。

你可还记得呀?往昔之时QQ呈现出怎样的情形呢?发送一句“在吗”,倘若对方未曾接收到,你全然无从知晓。

现在的用户可不一样。

丢一条消息,客服工单直接爆掉。产品经理第二天就杀到工位。

宁可慢点,也不能丢。

千万别忘了心跳

我踩过这个坑。

时间段内,系统连接数攀升,然而推送成功率与起始状态相近。

翻代码看了半天才反应过来——心跳检测形同虚设

相当数量的僵尸连接附着于服务器之上,占据着内存以及CPU,而真正的用户却连连接的地方都没有。

进行心跳间隔的设置,开展定期的检查工作,将超时的连接直接予以踢掉。服务端会同时展开检查,客户端自身也会进行检查。

效果立竿见影,连接健康度从70%提升到95%。

群消息是分布式下的噩梦

私聊还好说。一对一发完就完事儿。

群聊呢?一个500人的群,发一条消息,服务器要推500次。

万人群?我这辈子都不想碰。

通常来讲,是进行写扩散,即消息抵达服务端之后,依据群成员列表逐个去投递。又或者是开展读扩散,也就是存储一份,不管是谁来读取,都由其自行拉取。

各有各的苦。写扩散服务端压力大,读扩散客户端拉取慢。

怎么办?长轮询+M后面加缓存。或者干脆混合模式。

但这问题其实到现在,我也没有完美答案。

压测做了三遍,还是怕

第一次压测直接崩了。

第二次压测撑住了10w连接,发现内存泄漏。

第三次压测撑住50w,发现日志打印太狠,磁盘写满了。

每一次都有新问题。每一次都觉得自己傻逼。

现在学聪明了。

在进行压测之际,要将监控妥善布置好,此监控涵盖CPU,还有内存,以及带宽,另外包括连接数,再就是消息延迟百分位数。

特别是P99延迟,低于500ms才算合格。

并且,不能够仅仅去看平均值,平均值会对你造成误导,而实际上真正存在的问题在于那占比1%的速度较慢的用户,这些用户是会责骂你的。

最后说点心里话

经历了从事IM推送工作的这几年时间,内心深处所获得的最为深刻的体会便是,永远都不要去相信“应当不会存在问题”这种说法。

你觉得没问题,那就一定有问题。

高并发这东西,你永远不知道哪块短板会最先断裂。

会有可能是代码,会有可能是网络,会有可能是运维人员操作上稍微疏忽,会有可能是用户所使用的设备质量欠佳。

但话说回来。

当那一万条消息真的都在500ms内送到了对方手机上的时候。

当深夜看监控面板,发现一切平稳运行的时候。

那种感觉。

还挺爽的。

写着写着就晚了。

肚子饿了。拉面去了。

明天继续搞那个离线消息的重复推送问题。据说又是新坑。

不过也算了吧。写的也不是啥NB的文章。

就是个踩坑记录。

希望对你有用。

就这样。

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

七爪网 行业资讯 IM消息推送开发:从崩溃到千万级连接的逆袭之路 https://www.7claw.com/2827758.html

七爪网源码交易平台

相关文章