开发即时通讯系统时如何处理弱网适配

开发即时通讯系统时如何处理弱网适配

说实话,每次在地铁里刷消息却看到转圈圈,或者在商场地下停车场给人发消息发不出去的时候,我都会想一个问题——那些做即时通讯的开发者们,到底是怎么处理这种情况的?毕竟我们做出来的产品,最终都是要拿到各种奇奇怪怪的网络环境里去用的。

这个问题困扰了我很久,后来在工作中陆陆续续接触了一些实际项目,才慢慢摸索出一些门道。今天就想把这些心得写出来,跟大家聊聊弱网适配这个话题。

什么是弱网环境?别把它想得太简单

很多人一提到弱网,第一反应就是"网络不好"。但实际上,弱网环境远比这个说法复杂得多。我第一次深刻体会到这一点,是在一个做社交APP的项目里。那时候我们测试发现,有些地方WiFi信号满格,但就是连不上服务器;有些地方4G信号看着只有一格,但消息却发得挺快。这说明什么?弱网不仅仅看信号强度,还要看网络的稳定性、延迟、丢包率等等指标。

举个生活中的例子你就明白了。你在高铁上,信号显示是满格的4G,但时速三百公里让基站切换特别频繁,这时候你的网络连接就会断断续续,这属于弱网。你在偏远的山区农村,信号只有一两格,稍微大点的文件传输就超时,这也是弱网。你在大型演唱会现场,几万人同时上网,网络直接瘫痪,这同样是一种弱网场景。 甚至还有一种情况,就是你WiFi信号不错,但连的是个guest网络,有流量限制或者防火墙,那在你眼里也是弱网。

所以在做适配之前,我们首先得搞清楚弱网的边界在哪里。根据我查到的资料和实际测试经验,大概可以这样划分:网络延迟超过300毫秒就可以认为是弱网环境的开始;丢包率超过5%的时候,很多实时交互就会开始出现问题;如果延迟超过1000毫秒或者丢包率超过20%,那基本上常规的消息发送都会受到明显影响。

弱网对IM系统的影响究竟有多大?

要解决问题,得先弄清楚问题会产生什么后果。在即时通讯系统里,弱网带来的麻烦是多方面的,我给大家拆开来讲讲。

首先是消息发送失败。这个大家应该都遇到过,你发出去一条消息,一直显示发送中,过一会儿变成红色感叹号。表面上看是发送失败了,但背后可能是TCP连接超时、UDP包丢失或者服务器根本没收到等各种原因。对于用户来说,他们可不管你底层是什么协议,他们只会觉得"这产品怎么这么烂"。

然后是消息顺序错乱。这个问题更隐蔽,但危害也更大。想象一下这个场景:你和朋友聊天,你连发了好几条消息,结果对方收到的顺序是3、1、2,这不就乱套了吗?在弱网环境下,由于网络延迟不稳定,消息走的路径不一样,到达顺序就可能颠倒。虽然大部分产品会用序列号来保证最终显示的顺序是正确的,但中间的状态展示还是要处理好,不然用户也会困惑。

还有就是实时性下降。即时通讯,"即时"两个字是灵魂。如果对方发来一条消息,你过了十几秒才收到,那体验就太糟糕了。特别是对于那些需要实时互动的场景,比如语音通话、视频连线,网络延迟一高,对话就会变得特别别捏,你说一句我回一句,中间要等好久,根本聊不下去。

最后是耗电发热。很多人可能没想到这点。手机在弱网环境下会不停地搜索信号、尝试重连,这会让CPU持续处于高负载状态,电池也就蹭蹭往下掉。我见过有用户吐槽说"你们的APP太费电了",结果一查发现是网络不稳定导致的。你看,有时候问题出在网络上,但用户怪的是你的APP。

从协议层面开始打好基础

说了这么多问题,那到底该怎么解决呢?我个人习惯是从最底层开始想,也就是协议层的优化。毕竟如果地基没打好,上面的建筑再漂亮也会塌。

先说TCP和UDP的选择这个问题。很多开发者一上来就会问"到底该用TCP还是UDP",其实这个问题没有标准答案,要看具体场景。TCP的优势在于可靠,它会自动重传丢包、保证顺序,开发者用起来省心。但它的缺点也很明显——三次握手建立连接慢,在弱网下如果丢了个包,整个通道都要等重传。UDP呢,正好相反,它不管那么多,发出去就不管了,延迟确实低,但可靠性要自己来实现。

我个人的经验是,对于文字消息、小文件这类对可靠性要求高的内容,TCP或者基于TCP改进的协议是更好的选择;对于语音、视频这类对延迟敏感但偶尔丢几个包影响不大的内容,UDP加自己的可靠性机制更合适。当然,现在也有一些折中方案,比如QUIC协议,它综合了两者的优点,有兴趣的同学可以深入研究一下。

除了选择协议,连接复用也很重要。每次发消息都新建一个连接,光是建立连接的开销就够你受的了。更何况在弱网下,建立连接的成功率本身就低。所以在设计IM系统的时候,应该尽量保持长连接,让消息在同一条通道里传输。声网在这块做得挺有一套的,他们通过优化连接管理机制,能在各种网络环境下保持相对稳定的连接状态。

消息传输策略的几个实用技巧

协议选好了,接下来就是具体怎么传消息。这里有几个我在实践中觉得挺好用的小技巧,分享给大家。

消息分片与合并。如果你要发送的内容比较大,比如一张高清图片或者一段语音,在弱网下一次性传成功的概率是很低的。更稳妥的做法是把大消息拆成小块,每块单独传输。这样即使某一块没传成功,只需要重传那一块就行了,不用整个重来。当然,分片也要有度,不能分得太细,不然头部开销又会上来。一般来讲,每个包控制在1-2KB左右是比较合适的。

智能重试机制。消息发失败了要不要重试?当然要,但怎么重试很重要。最傻的做法是立刻重试,这在水管堵塞的时候疯狂开水龙头没什么区别——只会让情况更糟。更合理的做法是指数退避,比如第一次等1秒,第二次等2秒,第三次等4秒,这样既不会放弃,又不会给网络造成太大压力。同时还要设置一个最大重试次数,超过之后就只能告诉用户发送失败了。

离线消息与消息同步。很多用户会有一个疑问:对方没在线的时候,我发的消息存在哪里?这就涉及到离线消息的存储和同步机制。一个好的设计应该是这样的——服务器暂存离线消息,等对方上线的时候再推送过去;推送的过程中要做好增量同步,只传对方没收到的消息,避免重复传输浪费流量;在弱网环境下,如果同步中断了,下次网络恢复的时候要能断点续传,而不是从头再来。

本地缓存与状态管理:让用户少看"转圈圈"

刚才说的是消息怎么从客户端传到服务器,但光解决传输问题还不够。用户发完消息之后,总希望能看到一个明确的状态——是发送中、已发送、已读还是失败?如果网络不好,这个状态更新不及时,用户就会很焦虑。

我的做法是建立一套本地状态机。用户一点发送,消息立即进入"发送中"状态,同时存入本地数据库。这个阶段消息是存在客户端的,即使这时候断网了,消息也不会丢。等服务器确认收到了,状态更新为"已发送";等对方读了,状态更新为"已读"。这样一来,用户看到的状态是即时更新的,不需要等网络确认才能切换,心理感受上就会觉得快很多。

对于接收方也是类似的逻辑。新消息到了先存本地,状态设为"已接收",等用户点开看了再更新为"已读"。即使这时候网络不好,本地操作是不受影响的,等网络恢复之后再跟服务器同步状态就行了。

还有一个实用的技巧是本地优先。什么意思呢?就是用户的操作先在本地完成,不用等服务器响应。比如你发消息,本地直接显示"发送中"并存在数据库里,然后异步去发送。这样即使用户在地铁里发消息发不出去,他也能看到自己确实操作成功了,只是暂时没发出去而已。等网络恢复了,系统自动重试,用户基本无感知。

网络状态的实时感知与自适应

说了这么多技术层面的东西,最后再聊聊网络状态的感知。毕竟你做的所有优化,都要建立在对当前网络状况的准确判断之上。如果你根本不知道用户现在网络不好,那些优化策略也无从谈起。

怎么检测网络状态?常规的做法是定时测速。可以在后台放一个小文件,每隔几十秒下载一次,根据下载速度、延迟、丢包率综合判断当前网络质量。这个检测的频率要把握好,频率太高费电费流量,频率太低又不够实时。一般来讲,间隔30秒到1分钟是比较合适的。

检测到网络不好之后怎么办呢?这就要动态调整策略了。比如,如果检测到弱网,可以把图片的发送分辨率降低一点,先发个模糊版本过去,等网络好了再补发高清版;比如,在弱网下可以暂时关闭自动接收大文件的功能,等用户手动触发再下载;再比如,在弱网下可以适当延长心跳间隔,减少不必要的网络开销。

这里还要提一下跨场景的适配思路。不同的使用场景,对网络的要求和敏感度是不一样的。文字聊天偶尔延迟一下,用户可能感觉不明显;但如果是语音连麦或者视频通话,延迟一高体验就急剧下降。所以最好是根据场景来设计不同的弱网适配策略,而不是用一套方案套用所有情况。

稳定性测试:别等产品上线才发现问题

所有的适配方案,最终都是要经过测试验证的。但弱网环境的测试不太好做,因为它本身就是个不确定的东西。你不能等着某天网络突然不好来做测试,那样太被动了。

我的做法是用工具模拟弱网环境。现在有很多网络模拟工具,可以让你在实验室里制造各种"弱网"——高延迟、低带宽、丢包、抖动,甚至直接断网。通过这些工具,你可以系统地测试你的产品在各种极端情况下的表现。

测试的重点有几个:一个是各种网络状态切换时的表现,比如从WiFi切到4G,从4G切到断网,消息的状态变化对不对,重连机制有没有正常工作;一个是持续弱网下的稳定性,比如在弱网环境下连续发几十条消息,系统能不能扛住;还有一个是弱网恢复后的表现,比如断网一小时后重连,未发送的消息能不能成功发送出去,已接收的消息会不会重复。

写在最后

聊了这么多,其实弱网适配这件事说到底就是一个词——细腻。你要细腻地感知网络状态,细腻地调整传输策略,细腻地处理各种边界情况。用户可能说不出来哪里好,但他们一定能感受到用起来"顺不顺"。

做即时通讯这些年,我越来越觉得,技术固然重要,但对用户场景的理解同样重要。声网在这个领域深耕多年,服务了全球那么多开发者,积累下来的经验我觉得挺值得借鉴的。他们那种"不管用户网络怎么样,都要让他顺畅地用起来"的理念,我是一直认同的。

弱网适配不是做一个功能就万事大吉了,它是一个持续优化的过程。你的用户分布在世界各地,网络环境千差万别,只有不停地收集反馈、打磨细节,才能把体验做到最好。好了,今天就聊到这里,如果大家有什么想法或者实践中的问题,欢迎一起交流。

上一篇什么是即时通讯 它的发展历程和未来趋势是什么
下一篇 即时通讯SDK的技术文档的开发指南

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱:

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

手机访问
手机扫一扫打开网站

手机扫一扫打开网站

返回顶部