XMPP 协议适合用来做移动 IM 么 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
jwfing
V2EX    程序员

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

  •  6
    &nsp;
  •   jwfing 2014-09-02 10:26:06 +08:00 21955 次点击
    这是一个创建于 4059 天前的主题,其中的信息可能已经有所发展或是发生改变。

    XMPP 协议是什么

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

    1,XMPP 的三种基本角色:客户端、服务器和网关,通信能够在这三者的任意两个之间双向发生。服务器端同时承担了客户端信息记录、连接管理和信息路由的功能。网关则承担着与异构系统的互联互通功能。在 RFC 3920 XMPP Core 中对 XMPP 网络结构有一个描述:
    <pre>
    C1—-S1—S2C3
    |
    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=“[email protected]/contact” to=“[email protected]/contact”>
    <status>online</status>
    </presence>

    2.2 Message
    用于在两个用户之间发送消息。消息结构举例如下:
    <message from=“[email protected]/contact” to=“[email protected]/contact” type=“chat”>
    <body>hello</body>
    </message>

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

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

    XMPP 聊天的过程如下:

    • 所有从一个 client 到另一个 client 的消息和数据都要经过 XMPP Server;
    • client1 连接到Server;
    • server 利用本地目录系统的证书对其认证;
    • client1 指定 client2 目标地址,让 server 告知 client2 目标状态;
    • server 查找,连接并进行互相认证;
    • client1 和 client2 进行交互。

    XMPP 系统实测

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

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

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

    • Case1-搭讪
      猿:你吃饭了吗?
      MM:吃了
      猿:你在干什么呢?
      MM:上网
      猿:你那天气好吗?
      MM:还可以
      猿:你最近忙吗?
      MM:不忙
      猿:。。。。
      猿:哦,这样啊,我就想知道你在干什么,那你继续忙吧,拜拜
      MM:拜拜

    • Case2-请教
      A:嘿 //是什么意思啊?
      B:嘿.
      A:呃 我问你//是什么意思?
      B:问吧.
      A:我刚才不是问了么?
      B:啊?
      A:你再看看记录…
      B:看完了.
      A:……所以//是啥?
      B:所以什么?
      A:你存心耍我呢吧?
      B:没有啊 你想问什么?

    • Case3-约会
      女:你能让这个论坛的人都吵起来,我今晚就跟你走.
      某猿:PHP是最好的语言!
      论坛一下炸翻了天,女:i服了u,我们走吧,你想干啥都行.
      某猿:今天不行,我一定要说服他们,PHP必须是最好的语言
      某女:…….

    • Case4-借钱
      A:哥们儿,有钱吗?
      B:有
      A:借我点呗?
      B:啊?你说什么?
      A:借我点呗?
      B:不是,上一句?
      A:有钱吗?
      B:没有
      A:晕,程序重新请求一下,结果还不一样了!

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

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

    41 条回复    2015-10-25 00:01:35 +08:00
    erylee
        1
    erylee  
       2014-09-02 10:40:32 +08:00
    嗯,个人觉得XMPP不适合,我们在开发SLIMPP,GitHub项目: https://github.com/slimpp/
    chmlai
        2
    chmlai  
       2014-09-02 10:57:36 +08:00   1
    @erylee 你这个基于 MQTT 的好像不错, 可以问问现在是开发到什么状态了吗?, 留意下;
    ioth
    3
    ioth  
       2014-09-02 11:12:02 +08:00
    关注,现在要做一个。
    ahu
        4
    ahu  
       2014-09-02 11:16:03 +08:00
    注册了下,貌似还不能用
    erylee
        5
    erylee  
       2014-09-02 11:19:44 +08:00
    @chmlai 基础协议刚开发完,比如iOS的CocoaMQTT, erlang的mqtt server。现在开发Android的一个Demo,0.1版本应该在10月发布,然后迭代协议到1.0
    a2z
        6
    a2z  
       2014-09-02 11:22:16 +08:00
    XMPP用的XML,overhead太大了,大部分情况下结构描述比信息本身都大,非常不适合在流量有限的移动环境中使用。
    erylee
        7
    erylee  
       2014-09-02 11:28:52 +08:00
    @ahu 嗯,那个是协议开放站点,还只有web部分,手机端刚开始不久
    caoyue
        8
    caoyue  
       2014-09-02 11:40:47 +08:00
    XMPP 协议确实非常蛋疼,但是好处是足够完善,实现也很多,适合快速开发
    allenforrest
        9
    allenforrest  
       2014-09-02 11:47:18 +08:00   1
    SIP 也一样,开销非常大。

    但我还是很推崇 XMPP,优势在协议完备性、各种实现的成熟度等等方面。

    可以考虑在实现层面做一下改造,将 XMPP 报文在底层 TCP 传输时做一次编解码,转换成自定义的二进制格式,只需要改造一下 smack 库和 openfire 源码部分,对于上层应用开发来说完全透明,原来 smack 怎么用还是怎么用。

    底层编码后的冗余数据大大减少,节省流量和功耗。

    另外,考虑 XMPP 各种协议扩展较多,我们只需要针对最常用、最频繁的 XMPP 报文做编解码即可,其他不常用的仍然维持现有文本格式,对流量的贡献可控。
    est
        10
    est  
       2014-09-02 11:49:45 +08:00
    XMPP非常烂。离开了libjingle2的XMPP在桌面上都是一坨废物。
    lithiumdroid
        11
    lithiumdroid  
       2014-09-02 11:52:54 +08:00
    丰总,你还在写代码吗丰总
    huoxiaochai
        12
    huoxiaochai  
       2014-09-02 13:00:54 +08:00   1
    MQTT 值得你拥有!
    jwfing
        13
    jwfing  
    OP
       2014-09-02 14:30:56 +08:00
    @lithiumdroid 哈哈,写啊,我们公司工程师都写代码的。
    jwfing
        14
    jwfing  
    OP
       2014-09-02 14:31:46 +08:00   1
    推荐大家考察一下我们推出的聊天服务: https://avoscloud.com/features/realtime-messaging.html
    shawngao
        15
    shawngao  
       2014-09-02 14:43:29 +08:00
    哈哈,话说听了上期的teahour,说到AVOS就你一个在做IM,是这样吗?
    @jwfing
    jwfing
        16
    jwfing  
    OP
       2014-09-02 14:58:35 +08:00
    @shawngao 不是不是,我们有一个「小团队」在做 IM,主要负责的工程师是 https://twitter.com/Sunng
    shawngao
        17
    shawngao  
       2014-09-02 15:04:44 +08:00
    @jwfing 这样啊,那顺便了解一下你们的IM用C/C++、Golang或者其他?这方面我也是比较感兴趣的,所以想特别了解一下。
    pi1ot
        18
    pi1ot  
       2014-09-02 16:04:49 +08:00
    xml上面zip一下应该会有改善吧
    jwfing
        19
    jwfing  
    OP
       2014-09-02 16:08:23 +08:00   1
    @shawngao 我们服务器端是用 Clojure 写的,整个 AVOS Cloud(http://avoscloud.com) 的后端和网站,都是 Clojure 写出来的:)
    shawngao
        20
    shawngao  
       2014-09-02 16:47:27 +08:00
    @jwfing 对的,只是没想到IM也用Clojure, 感谢分享。
    hussion
        21
    hussion  
       2014-09-02 17:00:03 +08:00
    关注,我们暂时用socket.io实现,也在寻找比较靠谱的协议
    railgun
        22
    railgun  
       2014-09-02 17:15:15 +08:00   1
    不适合,首先传输用的是XML,构造和解析复杂,传输冗余大。
    另外,它对不稳定的移动网络不友好,经常会发生丢消息的情况。
    我认为成熟的移动IM,(或者根本不应该叫IM,移动网络的特点本身就决定了它不适合做即时通讯)应该同时兼容socket和HTTP,网络好的时候用socket保证实时性,网络差的时候用HTTP保证可靠性。
    还有一个血的教训是,不要让它负责除了聊天之外的其他任何事情,好友关系处理、用户资料设置什么的,最好都自己另外弄一套。XMPP自带的扩展和传输都很麻烦
    guoyang
        23
    guoyang  
       2014-09-02 18:44:31 +08:00 via iPhone
    作为一个趟过该浑水的人,我觉得自己搞私有协议远比xmpp好,因为用了之后你会发现里面的很多本来是好的东西,最后却变成了负担!特别对于移动网络
    erylee
        24
    erylee  
       2014-09-02 19:08:48 +08:00
    @railgun 非常有道理,我们直接JSON/HTTP+MQTT混合,网络好用MQTT推送,网络差通过HTTP同步。协议层面尽量支持Sync Pull和PUSH混合。
    jwfing
        25
    jwfing  
    OP
       2014-09-02 19:29:43 +08:00
    wenbinwu
        26
    wenbinwu  
       2014-09-02 19:52:25 +08:00
    hipchat?
    llbgurs
        27
    llbgurs  
       2014-09-02 20:03:15 +08:00
    可以看看我们的服务,基于mqtt的 yunba.io https://github.com/yunba
    icyalala
        28
    icyalala  
       2014-09-02 20:48:41 +08:00   1
    XMPP太重,如果需求不复杂,socket.io自己定义下协议就够用了。
    jwfing
        29
    jwfing  
    OP
       2014-09-02 21:12:45 +08:00
    @icyalala 嗯,AVOS Cloud的聊天服务就是自定义协议,并且也支持socket.io,最后我们的体会是根本不需要那些「开放」且「重量级」的协议!
    usufu
        30
    usufu  
       2014-09-03 09:00:48 +08:00
    有没有支持视频聊天的协议?除了xmpp扩展以外?
    pi1ot
        31
    pi1ot  
       2014-09-03 12:56:25 +08:00
    文本沟通的话IRC协议就够了,只是IRC更面向群聊。
    wupher
        32
    strong>wupher  
       2014-09-03 14:01:11 +08:00
    不适合。协议设计比较臃肿,XMPP协议最初设计时也没考虑移动端。
    <message>本身是可丢弃的,掉了也就掉了。使用XMPP一般考虑的是服务端客户端有开源实现可抄,二来就是开放性了。
    就现有开源实现来说,Erlang的那个ejabberd实现不太清楚,其它openFire, jabberd2感觉上量都有问题。群消息更是大深坑。
    文件传输与音视频这块,其实XMPP也就负责握个手,该怎么走RTCP,到时还得怎么走。
    量少浅尝可以,量大最终会开始动手改造。

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

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

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

    最后,无论使用任何协议,文本聊天都不会占用很多带宽,稍微浪费一点,问题不大。
    yunbaIO
        38
    yunbaIO  
       2014-09-04 11:24:47 +08:00   1
    不适合。虽然说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
        39
    loddit  
       2014-09-05 09:08:28 +08:00
    之前用过一阵子XMPP,感觉除了大家提到的XML冗余之外,还有一些限制它适用性的地方。
    最主要就是它有一下自己的业务设计,比如加入room需要客户端发送presence,需要先主动获取 roster 才能获取好友状态的更新。叫

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

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

    ps ejabberd 是比较有名的 erlang 实现,实现的xmpp协议比较全,而且性能貌似是目前最好的吧? 不如 openFire 吗?
    Wichna
        40
    Wichna  
       2015-07-27 13:10:47 +08:00
    好老的文了。很不错,顶一下。
    zonghua
        41
    zonghua  
       2015-10-25 00:01:35 +08:00
    @icyalala 可是是 openfire 等服务端有现成的消息系统,自己通过其他协议实现还要很多工作要做,小项目做这么多不现实。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5860 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 03:21 PVG 11:21 LAX 20:21 JFK 23:21
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86