用消息队列实现即时通讯3

消息队列(MQTT)

     前面讨论过消息队列传输的具体内容,那我们该用哪种方式进行呢?通过查阅网络资料,发现有两个方式值得借鉴。

     第一种方式每个帐号订阅自己的Inbox,而其他人都向这个Inbox发布信息,这种方式接收比较方便,但是发布时就比较麻烦。如群组有50人的话,一条消息就要发布50次,这和Http推拉信息有点类似。

     第二种方式,也是我正在使用的方式。每个帐号只订阅自己的个人聊天信息,以及加入的群聊。主题以"/"进行分隔,个人聊天p2p/帐号,群聊group/组帐号。这种方式发送群消息时只用publish 到group/组帐号,避免太多群成员发布次数过多的问题,也是个人认为比较合理的方式。下面将简单演示一下个人聊天方式:

一旦登录成功,自己订阅p2p/自己帐号,

A订阅 p2p/A

B订阅 p2p/B

A对B发送聊天信息:  A publish "Content" 到p2p/B 

由于B已订阅p2p/B,所以B将收到 “Content"信息,

同理,B回复信息,则向 p2p/A publish "Reply",

A 收到:"Reply"

    这样就完成简单的个人聊天,由于其他帐号没有订阅p2p/A,p2p/B所以也就无法接收到相应信息。当然,如果非要说其他帐号强制订阅p2p/A,p2p/B,不就能接收到他们私聊信息吗?是有这样的情况,但现在只能在客户端进行控制,强制不发生这种情况。理想的情况是订阅也要根据token进行,发布同样必须验证token,貌似阿里有带token的mqtt,没有认真研究,这些关于MQTT深入话题将要二期或三期进行研究。

    这种方式群聊就比较简单,新建群group1后,A加入group1,B加入group1后,

A 订阅 group/group1

B 订阅 group/group1

A要发送信息到group1 :A publish ”content“ group/group1

A,B,以及其他人员都会收到  "content"信息,此时msgId就起到了关键性作用,由于发送都已经有了此消息,就可以通过msgId避免重复。

系统消息

    首先定义系统消息主题固定格式: sys/类型[/类型结果]/帐号

因为系统消息大多都是有针对性的(广播新闻类除外,暂时没考虑这一块),比如A添加B为好友,系统会发布 添加好友信息到  sys/addP2p/B 

B同意后,系统会发布 同意信息到 sys/addP2p/ok/A ,所以A和B都要订阅相关的系统主题。订阅方式:用户只需要分别订阅 sys/+/帐号,sys/+/ok/帐号,sys/+/no/帐号。

说明

    为什么要订阅三个而不是订阅sys/#/帐号,因为订阅主题是用#号建议放在最后(没有强制规定,但是放在中间将忽略后面帐号),就没办法区分帐号

综上所述,当用户登录后MQTT连接成功,客户端应该向MQTT订阅:

p2p/帐号

sys/+/帐号

sys/+/ok/帐号

sys/+/no/帐号

循环参加的所有群组订阅 group/group帐号 (订阅零个或多个)

代码片段:

private static String myTopic = MessageTypes.P2P + "/" + APIX.account;
//这个表示,可能有一个,或多个情况的
private static String sysTopic = MessageTypes.SYS + "/+/" + APIX.account;
private static String sysTopicok = MessageTypes.SYS + "/+/ok/" + APIX.account;
private static String sysTopicno = MessageTypes.SYS + "/+/no/" + APIX.account;
// 订阅myTopic话题
client.subscribe(myTopic, 1);
//订阅系统消息
client.subscribe(sysTopic, 1);
client.subscribe(sysTopicok, 1);
client.subscribe(sysTopicno, 1);

if (APIX.current != null) {
   List<ImGroup> groupList = APIX.current.getGroups();
   if (groupList != null) {
       for (ImGroup group : groupList) {
           String sb = MessageTypes.GROUP + "/" + group.getAccount();
           client.subscribe(sb, 1);
       }
   }
}

预备知识基本上将完,具体的实现将在后面进行更详细讲解。

章,下一期专门讲解消息队列相关内容

猜你喜欢

转载自www.cnblogs.com/wavaya/p/10336183.html