XMPP 和 OpenFire

XMPP

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

XMPP 地址格式

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

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

  • (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就存储。dom

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

 

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

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

<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 么?
http://www.javashuo.com/article/p-wlrgvmnd-bn.html 

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