XMPP 是老牌的即时聊天协议,像 Google Hangouts, WhatsApp Messenger 等即时聊天程序都是基于 XMPP 的。
而 MQTT 是最近几年随着物联网行业的发展,才慢慢进入公众视线的,像 Facebook Messenger App 使用了 MQTT 协议。
MQTT 的特点在于报文小,协议简单,提供了三个 QoS 级别。这几个特性是专门为网络环境复杂的物联网(IoT)场景设计的。
XMPP 特点在于协议和扩展协议成熟,功能完善,专门为即时聊天(IM)场景设计。
两者无法直接比较优劣。就像老虎和狮子其实无法比较真实实力,因为一个踞卧在长白山,一个奔跑在非洲大草原,要较量怎么也得放到同一个战场。但问题是战场选在哪儿都不合适。放在草原是偏袒狮子,放在森林是偏袒老虎,放在动物园却都没了脾气,怎么也打不起来了。
对于这两个协议来说,首先 XMPP 依赖 XML 协议,所以放在 IoT 场景里过重,基本不合适,很少有人用。而另一方面虽然 MQTT 协议本身过于简单,放在实时聊天协议里的话,多数功能是要自己定制协议来实现的,但总归可以用。
按照这个道理,比较就只能放在 IM 领域才有真实意义。
做技术选择一直是程序员和设计者头痛的事情,放在 IM App 设计的初期,大概就归结为两个问题:
- MQTT 被越来越多的用在 IM 应用上,XMPP 是要退出历史舞台了么?
- 我的 IM App 到底该选用 MQTT 吗?
为了回答上面的两个问题,我们需要逐一考虑使用 MQTT 实现常见 IM 需求的方式,并分析其优缺点。
(现在很多人的技术选择已经很简单了 -- 什么流行用什么)
性能
对于移动设备上的 IM App 来说,电量损耗是一个需要认真对待的问题,在这方面,固定头部仅仅消耗 2 个字节的 MQTT 协议显然有着巨大优势。当然前提是设计良好的主题格式,消息体格式和长度。
使用 MQTT 搭配合适的二进制格式的消息体,让聊天信息交换和处理非常轻量。
IM 功能
XMPP 在 IM 的各个功能上的定义非常完善,而 MQTT 需要在基础协议之上自行实现。
认证
- XMPP: 通过 SASL RFC4422
- MQTT: 协议未定义,通常的实现方式是定制 CONNECT 报文中的 username 和 password 字段,因为 MQTT 只提供了这两个字段可以自行发挥。比如定义 username 为 {"uname": "Shawn", "dtype": "mobile"}, password 为 JWT。(MQTT 5.0 里添加了
AUTH
消息类型)。然后在 MQTT 后台处理 CONNECT 消息进行认证。
在设计的时候是需要仔细考虑的部分。
多设备
- XMPP: 核心协议里有定义,通过
resource
实现。比如用户 shawn@emqx.io 的两个设备分别是: shawn@emqx.io/pc, shawn@emqx.io/mobile。 - MQTT: 协议未定义。因为 MQTT 协议里,唯一标识设备使用的是
Client ID
,所以设计的难点在于,如何定义 Client ID 的格式,并且能够跟 IM 需求里的 username 做对应,并且实现多终端同步。常见的做法是:- 限制用户名里不能有特殊字符
'@'
,'/'
; - 对于 ClientID 的格式为 'username@device', 比如用户 "shawn" 的两个 ClientID: "shawn@pc", "shawn@mobile"。
- 对于用户 shawn 的这两个终端,通过订阅相同的主题来同步所有别人发来的聊天消息。比如都订阅主题:'p2p/talk/shawn'。并且向外发送消息时需要将消息复制到主题 'p2p/talk/shawn' 以同步发出的消息,这样做时,还需要忽略自己发出的同步消息。
- 限制用户名里不能有特殊字符
状态显示
- XMPP: XMPP Presence RFC 3921.
- MQTT: 协议未定义,可以通过订阅对方状态来实现:比如用户
未完成 2018年07月23日00:54:15