XMPP 协议适合用来做移动 IM 么

2014-09-02 10:26:06 +08:00
 jwfing

XMPP 协议是什么

XMPP(Extensible Messaging and Presence Protocol,前称Jabber)是一种以 XML 为基础的开放式实时通信协议,关于它的协议细节,网上已经有太多分析文章,我这里就不再赘述(而且,我也不可能比别人解释的更清楚)。简单来看这个协议,我们只需要知道:

1,XMPP 的三种基本角色:客户端、服务器和网关,通信能够在这三者的任意两个之间双向发生。服务器端同时承担了客户端信息记录、连接管理和信息路由的功能。网关则承担着与异构系统的互联互通功能。在 RFC 3920 XMPP Core 中对 XMPP 网络结构有一个描述:
<pre>
C1—-S1—S2—C3
|
C2—-+–G1===FN1===FC1
</pre>
这里 C1,C2,C3 表示 XMPP 客户端;S1,S2 表示 XMPP 服务器;G1 表示网关,用来负责 XMPP 协议和外部聊天协议的转换;FN1 表示外部消息网络的服务器,FC1 表示外部网络客户端。

大家可能会奇怪,这里为什么需要一个网关呢。这要从 XMPP 的来源说起。1996 年 Mirabilis 公司推出了世界上第一个即时通信系统 ICQ,不到 10 年,IM 就成了最流行的应用之一,MSN、Gtalk、雅虎即时通、AIM、Adium、Pidgin 等各种软件如雨后春笋般涌现,但是这些服务之间没有统一的标准,不能互联互通,XMPP 的设计目的就是为了实现整个及时通信服务协议的互通,让 IM 成为继 WEB 和 Email 之后的互联网第三大服务。

2,XMPP 的消息格式。

XMPP 协议的所有消息都是 XML 格式的,这是 XMPP 协议的另一个充满历史意味的选择,想当年 SOA / SOAP 一时间爆发起来,很多消息交换协议都采用了 XML 格式,但是不想 XML 很快就成了「大数据」的代名词。在 RFC 3920 XMPP Core 中定义了两个基础概念,XML Stream 和 XML Stanza,XML Stream 是两个节点之间进行数据交换的容器,它定义了顶层的XML节点 <stream>;XML Stanza 则定义了实体消息的具体语义单元,在 XMPP 中定义了 3 个顶层消息:

2.1 Presence
用于确定用户的状态。消息结构举例如下(每个 XML 的 node 还会有很多其他 attribute,为了简单起见这里省略,下同):
<presence from=“abc@jabber.org/contact” to=“def@jabber.org/contact”>
<status>online</status>
</presence>

2.2 Message
用于在两个用户之间发送消息。消息结构举例如下:
<message from=“abc@jabber.org/contact” to=“def@jabber.org/contact” type=“chat”>
<body>hello</body>
</message>

2.3 IQ
信息/请求,是一个请求-响应机制,管理XMPP服务器上两个用户的转换,允许他们通过相应的XML格式进行查询和响应。
<iq from=“abc@jabber.org/contact” id=“id11” type=“result”>
</iq>

3,XMPP 的交互流程。
XMPP 通过 TCP 传输了什么内容?在 QQ 里面,消息是使用二进制形式发送的,在 MSN 里面是采用纯文本指令加参数加换行符的形式发送的,而 XMPP 传输的即时通讯指令与他们相仿,只是协议的形式变成了 XML 格式的纯文本,这让解析更容易,方便了开发和查错,但是也带来了数据负载过重的缺点,而被人广为诟病。

XMPP 聊天的过程如下:

XMPP 系统实测

XMPP 协议的最主要的一点就是开放,不管是协议、客户端,还是 Server 端,都有成熟的实现方案。为了实际感受 XMPP 协议的聊天过程,我使用 asmack library + OpenFire 服务器搭建了一套完整的测试环境。

OpenFire 采用 Java 开发,是一个基于 XMPP 协议 的开源的实时协作服务器,它的安装和使用都非常简单,自带有一个内置的存储数据库(当然,你也可以使用独立数据库如Mysql等),并利用 Web 进行管理。其他类似的开源系统还有很多,eJabber、Tigase 也经常被用到。但是根据我们之前的经验,这些开源系统能支持的并发连接数都不高,要是有超过10万的用户同时连上来,对它们来说就快达到单机的瓶颈了,这时候一般都需要水平拆分,但是拆分之后服务器之间的 session 同步负担会大幅加重,对于性能又带来不小的抵消。所以这些系统大都被拿来做研究和测试用,很少见到大规模在生产环境中使用的。

好吧,我们还是来实际聊聊看。为了体现真实性,选取了程序员圈子里面较大概率可能发生的几段典型对话:

实际结果如下,我在 Nexus5 上面运行一个 IM app,连接上我自己搭建的 openfire 服务器,然后模拟了上面几段对话,在几个参与者的前提下,消息实时性还挺好,但在系统设置-》网络流量中看到,整个聊天过程中该 app 消耗掉的网络流量高达 36KB,聊天记录的文本文件大小为 8KB,也就是说网络流量的 70% 都消耗在 XMPP 协议层了,这个数字正好吻合了维基百科上吐槽的数据冗余率。

最后测试下来看,我个人感觉是,对于移动互联网来说,省电、省流量是所有底层服务的一个关键技术指标,XMPP协议看起来已经落后移动互联网了。

21186 次点击
所在节点    程序员
41 条回复
hussion
2014-09-02 17:00:03 +08:00
关注,我们暂时用socket.io实现,也在寻找比较靠谱的协议
railgun
2014-09-02 17:15:15 +08:00
不适合,首先传输用的是XML,构造和解析复杂,传输冗余大。
另外,它对不稳定的移动网络不友好,经常会发生丢消息的情况。
我认为成熟的移动IM,(或者根本不应该叫IM,移动网络的特点本身就决定了它不适合做即时通讯)应该同时兼容socket和HTTP,网络好的时候用socket保证实时性,网络差的时候用HTTP保证可靠性。
还有一个血的教训是,不要让它负责除了聊天之外的其他任何事情,好友关系处理、用户资料设置什么的,最好都自己另外弄一套。XMPP自带的扩展和传输都很麻烦
guoyang
2014-09-02 18:44:31 +08:00
作为一个趟过该浑水的人,我觉得自己搞私有协议远比xmpp好,因为用了之后你会发现里面的很多本来是好的东西,最后却变成了负担!特别对于移动网络
erylee
2014-09-02 19:08:48 +08:00
@railgun 非常有道理,我们直接JSON/HTTP+MQTT混合,网络好用MQTT推送,网络差通过HTTP同步。协议层面尽量支持Sync Pull和PUSH混合。
jwfing
2014-09-02 19:29:43 +08:00
wenbinwu
2014-09-02 19:52:25 +08:00
hipchat?
llbgurs
2014-09-02 20:03:15 +08:00
可以看看我们的服务,基于mqtt的 yunba.io https://github.com/yunba
icyalala
2014-09-02 20:48:41 +08:00
XMPP太重,如果需求不复杂,socket.io自己定义下协议就够用了。
jwfing
2014-09-02 21:12:45 +08:00
@icyalala 嗯,AVOS Cloud的聊天服务就是自定义协议,并且也支持socket.io,最后我们的体会是根本不需要那些「开放」且「重量级」的协议!
usufu
2014-09-03 09:00:48 +08:00
有没有支持视频聊天的协议?除了xmpp扩展以外?
pi1ot
2014-09-03 12:56:25 +08:00
文本沟通的话IRC协议就够了,只是IRC更面向群聊。
wupher
2014-09-03 14:01:11 +08:00
不适合。协议设计比较臃肿,XMPP协议最初设计时也没考虑移动端。
<message>本身是可丢弃的,掉了也就掉了。使用XMPP一般考虑的是服务端客户端有开源实现可抄,二来就是开放性了。
就现有开源实现来说,Erlang的那个ejabberd实现不太清楚,其它openFire, jabberd2感觉上量都有问题。群消息更是大深坑。
文件传输与音视频这块,其实XMPP也就负责握个手,该怎么走RTCP,到时还得怎么走。
量少浅尝可以,量大最终会开始动手改造。

倒是阅读XMPP协议蛮有趣的,没想到里面有这么多纯搞笑协议的RFC。比如XMPP-二进制版。
jwfing
2014-09-03 17:18:58 +08:00
@wupher +1 openfire/ejabberd能支持的并发连接都比较有限
gfh110
2014-09-03 17:45:08 +08:00
大家应该看下xmpp产生的历史。当时它的目标是提供一种通用的协议来试不同厂商的im可以互相通信。
它的性能并不好,而且因为是xml协议并不适用目前国内还对流量敏感的用户,并发量也上不去
citysofa
2014-09-03 17:50:45 +08:00
不适合
siteshen
2014-09-03 18:42:36 +08:00
坐等IM开源……
popatry
2014-09-04 01:56:13 +08:00
> 整个聊天过程中该 app 消耗掉的网络流量高达 36KB,聊天记录的文本文件大小为 8KB,也就是说网络流量的 70% 都消耗在 XMPP 协议层了,这个数字正好吻合了维基百科上吐槽的数据冗余率。

首先,其实浪费的带宽并没有你想象那么高比例。因为你没有考虑IP层和TCP层的带宽占用。我估计这种短小聊天信息如果有8KB,那么TCP/IP包头加起来恐怕也有10KB到20KB了。那么算上这些带宽占用,XMPP协议层占用的带宽也就在50%左右了。

其次,XMPP基于XML协议层格式繁琐,但信息量并不高,所以如果要压缩,那么压缩率就会很高。XMPP协议通常要通过TLS加密,可以启用TLS压缩选项。

最后,无论使用任何协议,文本聊天都不会占用很多带宽,稍微浪费一点,问题不大。
yunbaIO
2014-09-04 11:24:47 +08:00
不适合。虽然说XMPP本身是一个非常完整的协议,而且扩展性相当好,也有一些很好的Broker。但它并不适合用来做移动IM。其中一个劣势@jwfing 已经提到,就是它本身协议承载数据比例太低,差不多70%的流量都是消耗在标签上。另一个麻烦的问题就是它的延迟大。我们试验过用XMPP来做一个简单的Connect和用户认正,不仅要用1K的流量,还需要5-7次的交互,换句话说,一个登录就是秒级的延迟(移动互联网一个环回大概就是400、500毫秒)。另一个缺点就是XMPP的编解码也是很重,因为它是纯文本的解析器,你要用纯文本去做,不管是编码还是解码都是比较重的,在移动环境下合适。


推荐用MQTT协议,它是二进制协议,而且本身非常精简,做移动网络环境下做IM非常合适,省电省流量。它的做法是一个订阅/发布系统,拿到权限的人就可以往频道里发消息,任何在这个频道里的人就可以收到。MQTT还是开放协议,有很多开源实现,可以用它的开源实现搭个环境来玩一玩。另外很重要的一点就是它的扩展很方便,它原来就留了两个两个命令字,再加上它协议头本身很轻,在它的扩展命令字上做一些简单的事情就可以扩展出很多命令字。


我们云巴yunba.io是基于MQTT协议做双向消息实时推送,也支持Socket.io。开发者可以使用云巴,快速搭建包括移动IM以内的各类型实时应用。可以稳定支持千万级亿级海量用户。我们设立多处主干机房,全国范围内消息延迟在0.2s以内。

我们也投入了大量时间精力研究实践实时海量数据通讯、统计、存储等问题。之前创始人还在ArchSummit上就这方面做了的分享,题目就是实时系统架构和实践,有兴趣的可以戳http://t.cn/RhUxmwN看视频,全程干货,当时也提到了协议选择的问题。

对了,还有一个基于云巴产品开发的移动IM开源Demo,或许有用哈,Github地址http://t.cn/RPxwZjQ
loddit
2014-09-05 09:08:28 +08:00
之前用过一阵子XMPP,感觉除了大家提到的XML冗余之外,还有一些限制它适用性的地方。
最主要就是它有一下自己的业务设计,比如加入room需要客户端发送presence,需要先主动获取 roster 才能获取好友状态的更新。叫

一般来讲采用 XMPP 主要的好处就是可以直接使用很多开源的产品。但是因为本身也算比较复杂,这些产品上做一些自己的定制就没那么容易。

在移动端我不熟悉,我觉得如果使用第三方的平台实现实时通信可能是比较快速的选择。

ps ejabberd 是比较有名的 erlang 实现,实现的xmpp协议比较全,而且性能貌似是目前最好的吧? 不如 openFire 吗?
Wichna
2015-07-27 13:10:47 +08:00
好老的文了。很不错,顶一下。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/131245

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX