利用消息队列MQTT,打造一款属于自己的IM社交软件

简介:

MQTT 是一种基于发布订阅模型的即时通讯协议,由于轻巧,开源,易用,耗能少,支持 QOS/遗言(WILL)等特性,正被广泛应用于物联网和移动互联网。

消息队列 MQ 提供了对 MQTT 协议的支持,完全兼容 MQTT 标准协议,但是在使用 MQ MQTT 时,对比标准协议,需要注意两点:
1. 父级 Topic 需要提前创建
根据标准 MQTT 协议,Topic 存在多级,且拥有动态的特性(不需要用户提前定义和创建),但是使用过消息队列 MQ 的用户都知道,MQ Topic是需要通过 MQ 控制台提前创建的,这是因为 MQ MQTT是队列(消息持久化),且 MQ 不仅支持 MQTT 协议,还支持 TCP, HTTP 协议的接入,为了能将不同方式接入的消息互通,比如:用 MQTT 方式发送的消息,用 TCP 方式可以收到;用 HTTP 方式发送的消息,用 MQTT 方式也能收到,故 MQ MQTT 做了以下变通:

定义第一级 Topic 为父 Topic,使用前,需要在 MQ 控制台创建父 Topic,子级 Topic 无需创建,直接在代码中使用。

2. MQ MQTT 支持 p2p,且不需要显示订阅
这一点弥补了标准 MQTT 协议不支持 p2p 的遗憾。而且通过 TCP/HTTP 接入的客户端都可以收发 p2p 消息。

MQTT Topic的动态特性给设计者们带来了很多发挥空间,但是有些地方需要注意:

1)名称不能带/和空格

2)短小精干,简洁明了

3)使用 UTF-8,避免不可见字符

4)在一些特殊场景里,考虑将唯一设备号嵌入到 Topic 名称,便于辨识消息发送者
比如,只有 client1 可以发布消息到client1/status, 且不能发布到client2/status,那么当你收到client1/status时,可以肯定就是client1发送的消息。

5)谨慎使用通配符#
比如,订阅 news/sport/#, 那么你就会收到下面所有这些 Topic 的消息
news/sport
news/sport/player1
news/sport/player2
news/sport/player1/score
不可预计的消息数量,会对接收端(移动端,嵌入式设备)造成负担。

6)业务可延伸
订阅关系需要事先建立,所以发送端和接收端都需要提前意识到 Topic 的存在,这就要求我们合理设计 Topic 的结构,在增加新业务需求时,适当增加子级 Topic 即可,而不用修改,甚至推翻 Topic 原先的结构。
比如,订阅李娜的新闻,可以设计成订阅 news/lina, 但是文体娱乐圈里有很多和李娜重名的,后续业务需要,用户想订阅网球李娜的新闻时,整个 Topic 结构将被迫改变,所以,在业务设计之初,尽可能在延伸性上多考虑一些。
这样设计较之前就更稳妥些:
news/sport/tennis/lina
news/sport/tennis/lina/ranking
news/sport/tennis/lina/score/australianopen

下面结合 MQ MQTT 特点,提供一个社交 IM 场景下的实现雏形,欢迎大家讨论。

准备工作:在 MQ 控制台创建父级 Topic 和 GroupID
每个设备接入 MQ MQTT 服务时,都要提供 Client ID,这是每个客户端的唯一标识,要求全局唯一。
Client ID 由两部分组成,组织形式为 GroupID@@@DeviceID。
GroupID: 需要在 MQ 控制台申请创建,用于指定一组逻辑功能完全一致的节点共用组名,代表一类相同功能的设备。
DeviceID: 每个设备独一无二的标识,由业务方自己指定,无需在 MQ 控制台创建。

我们在 MQ 控制台创建父级 Topic:IMS 和 GroupID:GID_IMS,且假设
用户A使用设备GID_IMS@@@DeviceID_A
用户B使用设备GID_IMS@@@DeviceID_B
用户C使用设备GID_IMS@@@DeviceID_C

场景1,用户A请求加用户B为好友,并进行一对一聊天

方案一,使用 p2p 消息。
优点是无需双方提前订阅(其实 p2p 功能也是通过订阅来实现的,只是用户在使用时无感知),缺点是如果DeviceID_B同时收到多个好友申请(见2),如何分辨是谁发送的请求呢?
从消息 Topic 是无法得知的,只能通过解析 message body 来辨识。

注意,p2p 消息,二级 Topic 必须是 p2p 字样,三级Topic是目标设备的 Client ID。

场景1_1

方案二,给每一个用户设计一个 Inbox,每个用户在客户端登录时都要订阅自己的 Inbox。
优点是每个用户收到消息时,可以通过解析 Topic 知道是谁要加他为好友,也能知道谁通过了他的好友添加请求。
当 USER B 收到消息 IMS/UserB/Inbox/Add/GFReq/UserA (见4),就知道是来自于 USER A 的好友添加请求。
当 USER A 收到消息 IMS/UserA/Inbox/Add/GFResp/UserB (见6),就知道是来自于 USER B 的反馈。

场景1_2

场景2,用户A关注好友B动态,B更新朋友圈,A收到更新

用户 A 想关注好友 B 的朋友圈动态,可以订阅 IMS/UserB (见1)。
好友 B 有好东东想晒一下,可以发布 IMS/UserB (见2),发布之后,所有订阅 IMS/UserB 的好友都可以看见这条分享(MQ MQTT 会负责将消息发送给所有订阅的好友)。
如果 A 不想看 B 的朋友圈动态了,那么就取消订阅 IMS/UserB (见4)。

场景1_3

如果是 B 不想让 A 看见自己晒的东东,该怎么办呢?
也可以利用 Inbox。
用户 A 登录时订阅 IMS/UserA/Inbox/Update/# (见2)
用户 B 发送一条消息到 IMS/UserA/Inbox/Update/UserB/Unsub (见3),A 在收到这条消息后,取消订阅 IMS/UserB (见5),在此之后,B 在朋友圈所有的分享,好友 A 都是看不到的。
当然,A 在收到 B 的取消订阅请求(见4)后,是弹窗通知到 A 本人(让 A 知晓被 B 拉黑)还是静默(A 被默默拉进 B 的黑名单),就完全由应用设计来决定了。

场景1_4

场景3,用户A邀请B,C好友进行群聊(B,C非好友关系)

群聊创建者 A 首先要订阅 IMS/Group123/# (见1)。
邀请用户 B, C 加入群聊,可以使用 p2p 消息(见2,4)。
用户 B, C 同意加入群聊,订阅 IMS/Group123/# (见6,7)。
加入群聊组中的成员 B 想要发言,可以携带自己的身份信息发布到 IMS/Group123/UserB (见8), 这样一来,所有订阅 IMS/Group123/# 的成员都能看到 B 的这条发言了。

场景1_5

场景4,逢年过节,给多个好友发送祝福信息(群发消息,不是群聊噢)

可以逐一给好友发送 p2p 消息,或者发送消息到各好友的 Inbox 中。
这种方式的缺点是需要多次 Publish,有几个好友,就需要 publish 几次(见4,6)。

场景1_6

不想 publish 多次,该怎么办呢?
Sorry,目前确实没有更好的办法。

其实我们希望可以创建一个虚拟 Group,好友们不用显示订阅这个 Group,由系统根据业务配置动态创建订阅关系。完成的效果是,好友们能收到发送给这个 Group 的消息,但是不会意识到这个 Group 的存在,因为客户端没有发起过订阅虚拟 Group 的动作(原理类似 p2p 订阅)。

目前 MQ MQTT 还不支持这样的功能,我们期待后续它可以提供这样功能的 Plugin,方便业务端扩展更多功能。

场景5,商业推广,系统给不同种类/定位的用户推送消息

想给不同地域的用户推送系统的新年祝福,消息的内容根据用户地域不同而变化。
正如之前的群发场景一样,使用 p2p 或者 Inbox 固然可以做到,但是整个系统,那么多用户,逐一发送并不是理想的方式。
而目前 MQ MQTT 又不支持虚拟 Group,如何完成这个功能呢?
业务设计之初,预留一个给系统广播使用的 Topic, 比如 IMS/System,每一个用户除了订阅自己的 Inbox,好友之外,也要根据自己的属地订阅系统预留的 Topic (见1,2)。
如:
北京用户订阅 IMS/System/Beijing
杭州用户订阅 IMS/System/Hangzhou

系统发送一条消息到 IMS/System/Beijing(见3), 所有北京用户都会收到(见4),系统发送一条消息到 IMS/System/Hangzhou(见5), 所有杭州用户都会收到这条消息(见6)。



用户登录客户端时,业务应用就需要预先判断其属地,并订阅相应的预留 Topic。
这种方案其实不够灵活,因为当后续扩展新业务功能时,程序需要升级(订阅新的 Topic 来满足新业务),但就目前来说,这也不失为一种可行的解决方案了。

轻量级,够灵活,开源易用,让您轻松,快速打造出一款即时通信应用APP, 心动了没?

目录
相关文章
|
23天前
|
消息中间件 JSON Java
开发者如何使用轻量消息队列MNS
【10月更文挑战第19天】开发者如何使用轻量消息队列MNS
63 5
|
18天前
|
消息中间件 存储 Kafka
MQ 消息队列核心原理,12 条最全面总结!
本文总结了消息队列的12个核心原理,涵盖消息顺序性、ACK机制、持久化及高可用性等内容。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
消息中间件 安全 Java
云消息队列RabbitMQ实践解决方案评测
一文带你详细了解云消息队列RabbitMQ实践的解决方案优与劣
65 9
|
22天前
|
消息中间件
解决方案 | 云消息队列RabbitMQ实践获奖名单公布!
云消息队列RabbitMQ实践获奖名单公布!
|
29天前
|
消息中间件 存储 弹性计算
云消息队列RabbitMQ实践
云消息队列RabbitMQ实践
|
1月前
|
消息中间件 存储 监控
解决方案 | 云消息队列RabbitMQ实践
在实际业务中,网站因消息堆积和高流量脉冲导致系统故障。为解决这些问题,云消息队列 RabbitMQ 版提供高性能的消息处理和海量消息堆积能力,确保系统在流量高峰时仍能稳定运行。迁移前需进行技术能力和成本效益评估,包括功能、性能、限制值及费用等方面。迁移步骤包括元数据迁移、创建用户、网络打通和数据迁移。
64 4
|
2月前
|
消息中间件 弹性计算 运维
阿里云云消息队列RabbitMQ实践解决方案评测报告
阿里云云消息队列RabbitMQ实践解决方案评测报告
73 9
|
2月前
|
消息中间件 监控 数据处理
解决方案 | 云消息队列RabbitMQ实践
解决方案 | 云消息队列RabbitMQ实践
52 1
|
2月前
|
消息中间件 弹性计算 运维
云消息队列RabbitMQ实践
本评测报告详细分析了阿里云云消息队列 RabbitMQ 版的实践原理、部署体验及核心优势。报告认为其在解决消息积压、脑裂难题及弹性伸缩方面表现优秀,但建议进一步细化架构优化策略和技术细节描述。部署文档详尽,对初学者友好,但仍需加强网络配置和版本兼容性说明。实际部署展示了其高可用性和成本优化能力,适用于高并发消息处理和分布式系统数据同步。为进一步提升方案,建议增加安全性配置指导、性能调优建议及监控告警系统设置。
|
1月前
|
消息中间件 监控 测试技术
云消息队列RabbitMQ实践 - 评测
根据反馈,对本解决方案的实践原理已有一定理解,描述整体清晰但需在消息队列配置与使用上增加更多示例和说明以助理解。部署体验中获得了一定的引导和文档支持,尽管文档仍有待完善;期间出现的配置文件错误及依赖库缺失等问题已通过查阅资料解决。设计验证展示了云消息队列RabbitMQ的核心优势,包括高可用性和灵活性,未来可通过增加自动化测试来提高系统稳定性。实践后,用户对方案解决问题的能力及适用场景有了明确认识,认为其具有实际生产价值,不过仍需在性能优化、安全性增强及监控功能上进行改进以适应高并发和大数据量环境。
42 0

相关产品

  • 云消息队列 MQ