前先后后作的IM和推送系统已经有好几个了,一直都想好好总结下,所以就有了这篇文章。在我刚学编程的那会儿,以为网络通讯是一个很牛逼和门槛很高的一门技术,可是随着开源技术的发展和互联网知识的共享,如今要写出高质量的网络通讯程序已经变得容易多了。sql
只要谈通信确定绕不开协议,鉴于本人经验下面只谈本人撸过的三种协议:编程
转自: http://www.yangguo.info/2015/08/17/%E6%BC%AB%E8%B0%88%E9%80%9A%E8%AE%AF%E6%9E%B6%E6%9E%84/服务器
XMPP(Extensible Messaging and Presence Protocol),也叫Jabber,它是基于稳定长链接网络环境所设计的,对于不够稳定和带宽小的移动网络不是很是合适。因为XMPP基于XML,因此流量大,流量问题对于移动网络来讲很是敏感,而后就是消息不可靠、CMWAP兼容、开源项目对协议实现不完善等问题,也是XMPP面临的问题。固然XML能够经过精简压缩来实现流量可控,目前这也是XMPP优化的可行方案,消息的不可靠能够经过扩展XMPP来实现ACK,随着3/4G的发展,CMWAP网关毕竟是末日黄花,可是开源项目对协议只是部分实现等问题,也是使用XMPP绕不过去的坎。Openfire是XMPP领域最知名的开源项目,它简单易用,是不少团队的首选方案,这是国内使用最多的开源方案。Openfire虽然优势不少,可是缺点也很多,最致命的就是它的分布式扩展能力很弱,当用户量很大的时候,水平扩展就成为它的瓶颈所在。还有一个不得不提的项目就是Tigase,这是笔者接触的第一个XMPP开源项目,它在分布式扩展能力上和架构设计上比Openfire强了很多。因为该项目开始是一个私人项目,如今好像在商业化,因此使用者并非不少,虽然国外有成熟案例,可是国内目前并很少,因此当时趟了Tigase的不少坑,目前平安好医生的聊天系统就是基于此搭建的。若是对Tigase感兴趣,能够阅读我以前写的一篇文章《Tigase集群方案及配置说明文档》。不论使用哪一个开源项目,虽然看起来开箱即用,可是要成为稳定成熟的产品,还须要深度的二次开发才行。网络
虽然XMPP有不少弊端,可是它的生态目前是最完善的,若是从成本角度来考量,XMPP是前期投入最小产出最快的。可是若是是搭建一个SAAS平台或者千万量级的IM,XMPP就不是最优的选择了。固然这是一家之言,国内外目前商业化的IM SAAS平台有好几家都是基于XMPP实现的,这个你们能够自行Google。架构
MQTT是轻量级基于代理的发布/订阅的消息传输协议,它的最大特色就是协议开销很是小,伴随着的就是协议简单(40多页)、网络带宽要求极低和移动设备省电。有幸接触到该协议是笔者在开发Android推送系统时,对它进行了较细致的研究,虽然最终方案中没有使用该协议,可是本身定制的私有协议也参考了不少MQTT的设计。MQTT整个协议的组成,能够分为三个部分:并发
每一个MQTT命令消息的消息头部都包含一个固定头部,固定头部的格式以下:异步
Byte 1
消息类型和标志字段分布式
Byte 2
剩余长度字段(至少1个字节,最多4个字节),采用big-endian模式存储高并发
Message Type优化
1 |
0:保留 |
保证消息可靠传输,默认为0,只占用一个bit,表示是否第一次发送,它不能用于检测消息重复发送。只适用于客户端或服务器端尝试重发PUBLISH, PUBREL, SUBSCRIBE 或 UNSUBSCRIBE消息,注意须要知足如下条件:
1 |
QoS > 0 |
此时,在可变头部须要包含消息ID。当值为1时,表示当前消息先前已经被传送过。
该标志位标明 PUBLISH 消息的交付质量级别:
仅针对PUBLISH消息。不一样值,不一样含义:
1:表示发送的消息须要一直持久保存(不受服务器重启影响),不但要发送给当前的订阅者,而且之后新来的订阅了此Topic name的订阅者会立刻获得推送。
备注:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送。
0:仅仅为当前订阅者推送此消息。
假如服务器收到一个空消息体(zero-length payload)、RETAIN = 一、已存在Topic name的PUBLISH消息,服务器能够删除掉对应的已被持久化的PUBLISH消息。
这个字节包含当前消息的剩余部分,包括变量头部和负载的数据。
可变长度的编码方式使用一个单独的字节使消息能够达到127字节的长度上限。协议限制最多4个字节,这样程序能够发送最大256M的消息。
上面即是最核心的固定头部的内容,至于可变头部和消息体能够本身查询资料,目前有不少公司在使用MQTT实现Android的推送,可是目前笔者暂时不知道谁家的IM在使用它。
一万人眼中就有一万个哈姆雷特,一样的一万人眼中就有一万个私有协议。应用场景、设计风格,都会致使协议的设计千奇百怪。例如:数据量传输大的场景,压缩方案可能也被设计到协议中,由于不一样的环境可能用到不一样的压缩方式;传输质量,咱们可能就默认某一个级别,可能就从协议中移除,具体的设计得靠经验和应用场景来设计。
一套很简单的架构,CM只负责链路的管理,链路和用户ID的关系维护在Redis中,SM负责业务逻辑和消息路由。CM和SM内部经过RPC调用,CM和SM内部所有采用事件驱动的方式,所有采用异步的方式。任何一个模块均可以水平扩展,而且SM若是达到很是复杂的地步,还能够拆分。最终的压力基本就到了Redis和Mysql,这些高可用和高并发的方案,已经很是成熟,就不用多说了。
下图是登陆流程和消息发送流程
鉴于笔者经验,开发的IM最多承载用户数也就百万级别,因此架构上或者设计方案不必定完美,仅供参考!
注意事项