文档章节

移动端即时通讯系统实践

杭城小刘
 杭城小刘
发布于 2016/07/25 11:36
字数 2323
阅读 41
收藏 2

1、即时通讯系统的需求

任何技术系统都来源于真实业务的需求,做架构设计之前应该先设定好目标。作为一个即时通讯应用,可以参考微信的使用体验,你需要保证以下特性:
1、实时。消息的接收端应该能够及时收到并处理消息。
2、不丢。需要保证所有的消息都顺利送达。
3、不重。重复的消息对用户来说是一种糟糕的体验。
4、保序。只要顺序一乱,消息根本没发看。
5、节能。流量可贵,电量可贵,能省则省。
6、安全。如果涉及敏感数据,安全必须重视。
7、流畅。卡顿的应用是不会被用户接受的。

2、关键技术点

为了保证消息的实时性,有两种思路:
1、长轮询方式,高频率地从服务端拉取新消息。这种方式其实就是传统的请求-响应模型,现在很多体育文字直播软件也采取这种方式。这种方法虽然简单,但有很多缺点。一是会产生很多请求,这对服务器的压力和用户的流量都是浪费。二是消息仍然不够及时,不考虑传输时间,最长的延迟就是轮询的间隔。
2、消息的生产者主动推送消息。这应该是更好的选择,可以解决长轮询的缺点。我们的即时通讯系统也会采用这种方式。使用长连接,而且连接必须是稳定可靠的,才能确保消息的实时性。

2.1 数据通信协议

        服务端与客户端之间需要协商好数据格式,这是数据传输和数据处理的基础。协议的设计需要着重考虑第一节提到几点需求。
        XMPP和MQTT是当前比较成熟的两种消息协议。如果能较好地处理你的业务需求,就没有必要重复造轮子。有很多企业的业务有特殊需求,可以考虑根据实际情况自定义协议,从头开始显然是不现实的,可以参考已经成熟的协议再做设计和开发。具体协议内容在此不详细展开,只做优劣的比较。

2.1.1 XMPP

XMPP是一种以XML为基础的开放式即时通讯协议。
XMPP的优点是安全,SASL及TL等技术的可靠安全性已内置于核心XMPP技术规格中。
XMPP 协议的最主要的一点就是开放,不管是协议、客户端,还是 Server 端,都有成熟的实现方案。
基于XML,它天生拥有很强的灵活性,可以在核心协议之上方便地进行定制化。Google Talk就是采用这种协议。
但是XMPP的缺点也很明显。首先,XMPP协议的方式被编码为一个单一的长的XML文件,因此无法提供修改二进制数据。其次,XML 有大量的标签冗余信息,网络流量的 70% 都消耗在 XMPP 协议层了,这在移动互联网时代,流量和电量是一个不可忽视的消耗。

2.1.2 MQTT

        MQTT协议是由IBM提出的基于发布/订阅模型的消息传输协议,相比于XMPP,它显得非常轻量小巧,协议内容包括固定头部+可变头部+消息体,最下的情况下头部只需要两个字节,在传输开销上有着巨大的优势,可以节省流量和电量。
MQTT可以保证消息的可靠性,它包括三种不同的服务质量(最多只传一次、最少被传一次、一次且只传一次),如果客户端意外掉线,可以使用“遗愿”发布一条消息,同时支持持久订阅。
        XMPP使用XML,是一个历史的选择,在现在移动应用的场景下,个人更加推荐MQTT。据了解,不少企业,包括做IM SDK的厂商,也是在MQTT的基础上进行自定义的扩展和修改。

2.2 连接的稳定性

移动互联网的场景下,网络环境经常变化,需要保证连接是稳定的。

2.2.1 心跳
        最经典的做法就是使用心跳,实时地检测连接状态。通常是客户端每隔一小段时间向服务器发送一个数据包,通知服务器自己仍然在线,并传输一些可能必要的数据。如果在一定时间内服务器没有响应,则认为连接可能已经断开,重新尝试连接。
伪代码如下:

while(true) {
    if (now - last_pong_msg > keep_alive) {
        socket_close();
        reconnect();
    }
    send_heartbeat_ping();
    // 只是为了表示每keep_alive时间段发一次心跳
    sleep(keep_alive);
}

       上述代码的心跳间隔是固定的。由于心跳包也是会消耗流量的,因此应该找到一个理想的心跳周期,在能敏锐地察觉连接变化的前提下,尽量大地增加周期间隔。因此可以做一个优化,是使心跳间隔动态增加。

2.2.2 多连接尝试
(1)多连接尝试
        考虑到不同地区不同网络运营商的情况下,用户可能因为网络限制,连接不上我们的服务或者比较慢。我们在实践中就发现,某些网络运营商将某些端口封禁了,导致部分用户连接不上服务。为了解决这个问题,可以提供多个ip和多个端口,客户端在连接某个ip比较慢的情况下,可以进行轮询,切换到一个更快的ip。
(2)长连接与短连接结合
        这只是一条退路,而不是常规武器。
在长连接实在连接不上的情况下,可以考虑做降级,使用短连接长轮询的方式进行替代。

2.3 服务质量

        系统的设计往往存在着取舍和妥协。正如TCP比UDP更加可靠,但它的负载会更高。
在即时通讯系统中也存在着取舍的问题,是追求极速送达,还是在传输上做可靠性的保证,确保不丢不重?不同的业务类型可能需要不同的服务质量,MQTT协议提供了三种服务质量,可以作为参考:
        QoS 0: 至多发送一次,发送即丢弃。没有确认消息,也不知道对方是否收到。针对的消息不重要,丢失也无所谓。
        QoS 1: 至少发送一次。发送之后,会等待接收方ack确认。在一定时间之内,如果没有收到ack,则会再发一次,一直到接收方收到。重发的消息会在头部有dup标示。这种QoS可以保证消息不丢,但接收方可能会有重复消息,需要做去重。如下图所示:

         QoS 2:有且仅有一次。可以保证不丢不重,但是通信压力高,需要多次握手。如下图所示:

3 客户端实现

3.1 消息处理

发送消息比较简单,只需要往某一个topic发布即可。
接收消息的流程如下:

        收消息:客户端需要保持一个长连接,并且确保连接稳定,如上章节所示。
        消息过滤:如果发送端不能确保消息不重(如mqtt中QoS为0或1),客户端需要做去重,因此消息需要有一个唯一的id。
        消息合并和分发:在实际使用场景中,往往有各种各样的消息类型(如聊天消息、系统通知等),对同一类型的消息可以做合并,以加快后续消息处理速度。而不同类型的消息则分发到各自的处理器当中,如存储到本地数据库,通知页面更新等)
        UI更新:客户端一般是使用列表来展示消息(iOS中是UITableView,Android中是ListView),而列表的数据量可能很大,数据源更新频率也可能很频繁,因此需要对列表做性能优化,以确保用户体验。以iOS为例,使用Instruments监控性能瓶颈的地方,对内存占用和CPU占用大户进行优化。确定问题后,常用的技巧有:对cell高度做缓存;简化UI层次结构;避免大量的离屏渲染;减少混合图层;等等。对症下药,各个击破。

3.2 其他

IM应用中,还有很多常用的实现需求,例如表情键盘,图片语音等多媒体的存储和下载队列等。但这不在系统实现的范畴中,将来后有文章进行详细阐述。

另外:关于Tcp三次握手和四次关闭握手有篇文章:http://blog.csdn.net/whuslei/article/details/6667471/讲的不错。

 

 

本文转载自:http://www.jianshu.com/p/718fd04d6cd9

共有 人打赏支持
杭城小刘
粉丝 14
博文 109
码字总数 54955
作品 0
杭州
iOS工程师
加载中

评论(1)

panda大侠
panda大侠
79
移动端IM中大规模群消息的推送如何保证效率、实时性?

本文原题为“大规模群消息推送如何保证实时性?”,来自瓜子二手车IM负责人:封宇,本次内容有修订,感谢原作者(原文链接在文末)。 1、编者注 众所周之,群聊是移动端IM的服务端技术难点所...

JackJiang2011
2017/11/20
0
0
移动端IM中大规模群消息的推送如何保证效率、实时性?

本文原题为“大规模群消息推送如何保证实时性?”,来自瓜子二手车IM负责人:封宇,本次内容有修订,感谢原作者(原文链接在文末)。 1、编者注 众所周之,群聊是移动端IM的服务端技术难点所...

JackJiang-
2017/11/20
158
0
现代IM系统中聊天消息的同步和存储方案探讨

本文原作者:木洛,阿里云高级技术专家,内容有删减和修订,感谢原作者。 1、前言 IM全称是『Instant Messaging』,中文名是即时通讯。在这个高度信息化的移动互联网时代,生活中IM类产品已经...

JackJiang2011
2017/11/24
0
0
Netty干货分享:京东京麦的生产级TCP网关技术实践总结

1、引言 京东的京麦商家后台2014年构建网关,从HTTP网关发展到TCP网关。在2016年重构完成基于Netty4.x+Protobuf3.x实现对接PC和App上下行通信的高可用、高性能、高稳定的TCP长连接网关。 早期...

JackJiang2011
2017/12/01
0
0
新手入门一篇就够:从零开发移动端IM

一、前言 IM发展至今,已是非常重要的互联网应用形态之一,尤其移动互联网时代,它正以无与论比的优势降低了沟通成本和沟通代价,对各种应用形态产生了深远影响。 做为IM开发者或即将成为IM开...

JackJiang-
2016/08/03
703
4

没有更多内容

加载失败,请刷新页面

加载更多

下一页

MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
35分钟前
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
0
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
1
0
设计模式之五 责任链模式(Chain of Responsibility)

一. 场景 相信我们都有过这样的经历; 我们去职能部门办理一个事情,先去了A部门,到了地方被告知这件事情由B部门处理; 当我们到了B部门的时候,又被告知这件事情已经移交给了C部门处理; ...

JackieRiver
今天
1
0
Android中的设计模式之命令模式

参考 《设计模式:可复用面向对象软件的基础 》5.2 Command 命令 对象行为型模式 《Android源码设计模式解析与实战》第11章 让程序畅通执行--命令模式 意图 将一个请求封装为一个对象,从而使...

newtrek
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部