导航

XMPP 和 OpenFire

Posted on 2016-08-30 16:30  蝈蝈俊  阅读(4951)  评论(0编辑  收藏  举报

XMPP

XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。是一种数据传输协议。
XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。

XMPP 地址格式

一个XMPP节点的唯一标示符jabber identifier(JID),即实体地址,用来表示一个Jabber用户,但是也可以表示其他内容,例如一个聊天室.

一个有效的JID包括一系列元素:

  • (1)域名(domain identifier);
  • (2)节点(node identifier);
  • (3)源(resource identifier).

它的格式是 node@domain/resource,node@domain,类似电子邮件的地址格式.

  • domain用来表示接点不同的设备或位置,这个是可选的,例如a在Server1上注册了一个用户,用户名为doom,那么a的JID就是 doom@serverl,在发送消息时,指明 doom@serverl 就可以了,
  • resource可以不用指定,但a在登录到这个Server时,fl的JID可能是 doom@serverl/exodus (如果a用Exodus软件登录),也可能是 doom@serverl/psi (如果a用psi软件登录).资源只用来识别属于用户的位置或设备等,一个用户可以同时以多种资源与同一个XMPP服务器连接。

 

XMPP 协议的 XML 格式:

image

这里有三个顶级 XML 元素: Presence、Message、IQ,每个的含义如下:

<Presence> 用来表明用户的状态,

如:online、away、dnd(请勿打扰)等。当用户离线或改变自己的状态时,就会在stream的上下文中插入一个Presence元素,来表明自身的状态.

<Message> 用于在两个jabber用户之间发送信息。

Jsm(jabber会话管理器)负责满足所有的消息,不管目标用户的状态如何。如果用户在线jsm立即提交;否则jsm就存储。

To :标识消息的接收方。
from : 指发送方的名字或标示(id)o
Text: 此元素包含了要提交给目标用户的信息。

 

< IQ > 一种请求/响应机制,

从一个节点从发送请求,另外一个节点接受请求,并进行响应.
例如,client在stream的上下文中插入一个元素,向Server请求得到自己的好友列表,Server返回一个,里面是请求的结果.

<iq > 主要的属性是type。包括:
Get :获取当前域值。
Set :设置或替换get查询的值。
Result :说明成功的响应了先前的查询。
Error: 查询和响应中出现的错误。

 

XML流


XMPP本质上是一种XML流技术。

客户端开始和XMPP服务器会话,会打开一个长时间的TCP连接,然后和服务器协商一个流。
一旦你和你的服务器建立了一个XML流,你和你的服务器可以通过流交换三个特殊的XML片段:<message/>,<presence/>,<iq/>.这些片段称为XML节。而且一旦你已建立一个XML流,你可以通过流发送无数个节。

下图是 C 客户端  S 服务器端 XML流的精简内容:

C:  <stream:stream>
C:  <presence/>
C:  <iq type="get">
           <query xmlns="jabber:iq:roster"/>
    </iq>
S:  <iq type="result">
           <query xmlns="jabber:iq:roster">
            <item jid="suke@skh.whu.edu.cn"xs/>
            <item jid="gmz@skh.whu.edu.cn"/>
            <item jid="beta@skh.whu.edu.cn"/>
        </query>
    </iq>
C:  <message from="suke@skh.whu.edu.cn" 
              to="beta@skh.whu.edu.cn">
           <body>Off with his head!</body>
    </message>
S:  <message from="lj@skh.whu.edu.cn"
              to="cyl@skh.whu.edu.cn ">
           <body>You are all pardoned.</body>
    </message>
C:  <presence type="unavailable"/>
C:     </stream:stream>

 

XMPP面临的问题:

    • XMPP是基于稳定长连接网络环境所设计的,对于不够稳定和带宽小的移动网络不是非常合适。
    • 由于XMPP基于XML,所以流量大,流量问题对于移动网络来说非常敏感,然后就是消息不可靠、CMWAP兼容、开源项目对协议实现不完善等问题,也是XMPP面临的问题。

数据负载太重:随着通常超过 70%的 XMPP 协议的服务器的数据流量的存在和近60%的被重复转发,XMPP 协议目前拥有一个大型架空中存在的数据提供给多个收件人。新的议定书正在研究,以减轻这一问题。

没有二进制数据:XMPP 协议的方式被编码为一个单一的长的 XML 文件,因此无法提供修改二进制数据。因此, 文件传输协议一样使用外部的 HTTP。如果不可避免,XMPP 协议还提供了带编码的文件传输的所有数据使用的 Base64。至于其他二进制数据加密会话(encrypted conversations)或图形图标(graphic icons)以嵌入式使用相同的方法。

XMPP 优化的一个方案是:

  • XML通过精简压缩来实现流量可控。
  • 消息的不可靠可以通过扩展XMPP来实现ACK

 

OpenFire

 

Openfire是XMPP领域最知名的开源项目,它简单易用,是很多团队的首选方案,这是国内使用最多的开源方案。Openfire虽然优点很多,但是缺点也不少,最致命的就是它的分布式扩展能力很弱,当用户量很大的时候,水平扩展就成为它的瓶颈所在。

 

消息握手

经常会有人发现,Openfire的两个客户端,在网络不稳定的情况下,会丢失消息。起初我也不知道到底发生了什么,直到后来,在测试中发现,当你用连接上通讯服务器后,直接拔了路由器,wifi异常断开,客户端与Server没办法握手告知TCP断线的事情,所以你会在一段时间内,服务器认为你在线,而实际你离线。这种情况在地铁、快速移动切换网络基站的情况下也经常有复现。此时Openfire收到关于你的消息会直接推送给你,而你此时又因为没有网络收取不到,所以消息丢失。

解决办法:消息进行握手,每条消息发给客户端,都需要客户端回复回执,否则一直保存在服务器。

心跳机制

因为上述问题,所以就要经常清理那些失效客户端,保证客户端和服务器状态同步。

如每15s - 60s 客户端定时发送一个小型的msg给服务器,服务器收到后回复一个callback。

如果服务器120s内没有收取到任何消息,那么close Session。

 

 

 

虽然XMPP有很多弊端,但是它的生态目前是最完善的,如果从成本角度来考量,XMPP是前期投入最小产出最快的。但是如果是搭建一个SAAS平台或者千万量级的IM,XMPP就不是最优的选择了。

 

 

 

参考资料:

漫谈IM通信架构
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
http://timyang.net/im/mobile-im-xmpp/ 

xmpp协议详解一:xmpp基本概念
http://www.jianshu.com/p/a94749385755 

即时通讯协议的选型之XMPP
http://www.biaodianfu.com/xmpp.html 

XMPP 协议适合用来做移动 IM 么?
https://segmentfault.com/a/1190000000656509 

http://www.mikewootc.com/wiki/net/protocol/xmpp.html