移动APP的IM后台架构浅析

IM(InstantMessaging 即时通讯)作为一项基础功能,很多APP都有,比如:手机QQ、微信、易信、钉钉、飞信、旺旺、咚咚、陌陌等。而IM如同我们日常生活中的水和电一样,必不可少,也是很多“社交”类APP必不可少的基础功能,而上面这些APP里面,微信最为出色。

如果作为一名创业者需要用到IM的功能,我建议是直接使用第三方提供的服务,比如:易信(网易的童鞋们记得要给我打赏哇,我看过它提供的DEMO和服务,确实很赞~),为什么不自己开发?你有单聊那就需要群聊吧,而在移动互联网时代,因为移动互联网的特点,导致对技术的门槛比PC上的IM要高不少,而IM做为基础功能又至关重要,传闻很多公司内部是不允许使用QQ的(原因是怕因为信息外泄,360肯定是不用QQ的,具体用啥我也不清楚了)。扯了这么多,准备切入正题...

移动互联网的一些特性:

1、弱网络 2、对电量、流量敏感; 如果你的APP提供的IM服务,一是慢、经常丢失消息二是还特别费流量、电量,你觉得用户有什么理由不卸载你的APP呢?而光解决弱网络这个问题就是一个比较深的坑,所以没有一定的技术积累或是资源投入还是建议不要往这里面跳了。

IM的基本原则:

1、消息收、发尽可能快(不快、不实时就不叫即时通讯了); 2、不能丢失消息(你把消息都丢失了,谁还敢用,跟钱存银行钱可能会丢差不多);

网络传输协议的选择

APP上的IM传输协议以TCP主为,同时支持HTTP,而PC上的QQ主要采用UDP协议(历史原因),手机QQ是否也采用了UDP还不太确定。如果要实现像微信一样,支持web版,可以用HTTP/HTTPS来实现comet或者直接使用websocket(低版本的浏览器不支持)

消息协议的选择

几个原则: 1、传输信息体积尽可能小,越小才能传的越快,失败重传的可能性也越低; 2、传输的数据是安全、可靠的,你不能明文传输吧,而序列化、反序列化又会影响你的性能(Java在序列化、反序列化上性能问题尤为突出); 3、易于扩展、可维护(产品加一项功能,不能说后端更新了,APP端无法解析就会更种报错,无法使用);

常用的聊天协议: 1、XMPP 基于XML的消息协议,调试方便,抓到XML能大概看懂什么意思,缺点就是太臃肿了,虽然方便扩展,但是太费流量,强烈不建议使用,用它实现的APP收发消息不会快到哪去; 2、自定义的二进制协议 二进制肯定是比XML的体积要小的,建议是自定义的二进制协议 + protobuf

协议的定制的话,可以参考MySQL或者Redis的协议格式,这里给出一个参考的格式(类MySQL的): 数据包长度(4 byte)+ 协议头(2 byte)+ 协议版本(2 byte) + 错误码(2 byte)+ 回执码(2 byte)+ 消息体(data body)

为了安全和性能方面的平衡,可以考虑将消息体进行简单的加密处理(可以简单的将指定的位置的字节进行顺序调整,比如第一位与最后一位进行对调都可以)。这样在传输的过程中不用反序列化就很容易知道当前这条消息它的消息头是什么,提升一些业务逻辑的处理效率。客户端在接收数据时,为了解决粘包的总是,肯定会有一个缓冲池(可能是环形缓冲池),而数据包的长度能避免粘包的问题。

简单的收发架构

连接层(主要维护客户端的连接与消息的中转) 逻辑层(用户会话的验证,业务逻辑验证,消息存取,异步的消息队列) 持久层(数据的存储,热冷数据,灾备)

基本的消息收发流程:发 -> 存 -> 推送通知 -> 拉取消息,同时消息采用基于版本号的设计来保证消息的顺序。

注:图片来自从0到1:微信后台系统的演进之路

=== 关于连接层 陌陌之前对外的PPT里讲到单台压测连接数达到70W,这个跟配置、带宽有很大的关系,而蘑菇街的技术博客提到他们单机并发连接10万用户,我觉得单台并发10万相对靠谱一些。

因为移动网络的不稳定性,比如iPhone来个电话或者按了电源键几秒后,网络都会中断,会导致socket的重连同时也产生非常多的TCP half-open,而防止TCP的half-open通常采用心跳包的机制,而心跳包的频率也是非常有讲究,假设使用移动网络,频率高了费流量不说,还会导致信令风暴【参见 从微信信令风暴谈起】。而时间太长就会导致服务端过多的连接消耗。而心跳的频率具体应该定为多少,建议的话20s左右,具体的时间还跟ISP运营商的策略有关,一条通道多长时间不用就要被回收掉,而如果重新建立一条通道这个时间就会变的比较漫长。

而服务端如何及时的清理half-open的连接呢 一种用轮询的方式,每一个连接发消息过来时更新最后收到心跳包的时间,每一少都定时检测所有的连接,超时了就主动断开连接,因为要循环所有连接所以系统性能受影响比较大。 另外一各就是每一个连接都有一个定时器,超时了自动就断开了,但这会导致系统的资源消耗过高,十万个连接就得有十万个定时器,明显不合理嘛。 还有一种就是时间轮片(Timing Wheel),详情可参考这里:基于时间轮 (Timing-Wheel) 方式实现的定时器

而关于连接这一块的优化,可以参考腾讯云提供的维纳期服务 https://www.qcloud.com/product/wns.html

后面二块非我所长,我就不具体深入写了,重点可参考微信的那篇文章。针对个人,微信为每一个人同步数据时产生一个唯一、递增的序列号,在高并发的场景下,这个又是如何设计的呢,有兴趣可以参考这篇文章,讲的非常详细:万亿级调用系统:微信序列号生成器架构设计及演变

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏web

vue项目在移动端(手机)调试

1392
来自专栏CDN及云技术分享

我是怎么一步步用go找出压测性能瓶颈

笔者要在线上服务器load日志并且重放来测一些机器性能指标。模拟机器资源比较少,相对的被模拟的线上机器日志量大,假设线上单机qps有1w,那么5台机器组成的集群...

1.8K35
来自专栏月牙寂

Golang分布式设计模式之-----分层设计

第一时间获取文章,可以关注本人公众号 月牙寂道长 yueyajidaozhang      

3815
来自专栏腾讯架构师的专栏

多核处理器下数据库系统日志管理器优化技术探讨

传统数据库的设计假设磁盘为主要存储设备,其性能取决于基于I/O代价模型的优化。然而,当前数据库运行的平台已逐渐转移到由多核处理器、大内存和以闪存为代表的低延迟存...

2521
来自专栏全华班

基于PHP爬虫的博客小程序

小程序后端是基于 Wext-server-thinkphp3.2 实现的数据爬虫,使用 ThinkPHP3.2 框架开发。Wext-server-thinkph...

3441
来自专栏zingpLiu

海量日志实时收集系统架构设计与go语言实现

日志收集系统应该说是到达一定规模的公司的标配了,一个能满足业务需求、运维成本低、稳定的日志收集系统对于运维的同学和日志使用方的同学都是非常nice的。然而这时理...

1292
来自专栏社区的朋友们

埋在MYSQL数据库应用中的17个关键问题!

Mysql的使用非常普遍,跟mysql有关的话题也非常多。要想掌握其中的精髓,可得花费不少功力,虽然目前流行的mysql替代方案有很多,可是从最小成本最容易维护...

2.4K2
来自专栏SDNLAB

分层安全用于通用客户端设备(uCPE)部署的准则

1535
来自专栏FreeBuf

美国邮政服务网站漏洞可暴露6000万用户数据,现已修复

美国邮政服务系统刚刚修复了一个严重的网站漏洞,该漏洞使得拥有usps.com帐户的任何人都可查看和修改约6000万用户的账户详情。

1203
来自专栏聊聊技术

原 《Linux内核分析》小节

4026

扫码关注云+社区

领取腾讯云代金券