mosca做聊天时遇到的重复发送问题
发布于 9 小时前 作者 sirius2707 117 次浏览 来自 问答

最近在用mosca这个组件做聊天,遇到几个问题,望大神们指点: 1,moscaSettings中backend使用redis,离线数据各方面没有问题,但是发生了数据顺序错乱的情况 2,使用rabbitmq或者zeromq时,数据顺序正常,但是发生了在线收到的消息,再次登陆时,又发送了一遍,redis只会发一遍 qos在关注和发送时都设置为1 不知道是服务器设置的问题,还是本身的策略就是如此, 另外我们客户端的messageId在发送时都是int型的自增长,但是查看数据库中存储的离线消息messageId变成了随机字符串

1 回复
  1. 数据错乱 如果你用的是 moscaredis 持久化,它取离线消息是 lrange 拉取再 forward 的,但是 redis 的离线只支持 0 ~ 10000 之内的离线消息,且离线消息的 TTL 是由用户自定义的,数据顺序乱世肯定会有的,你可以给每一条消息加一个创建时间来标记。

  2. 消息多发 并不是说 redisPUBLISH 多次,原因是因为你所使用的客户端库针对于在收到服务端推送的 PUBISH QoS1 消息报文时是否返回 PUBACK 报文,如果服务器收到 PUBACK 则认为这条消息已经成功送达客户端(该消息不是离线消息,下次客户端登录不在发送这个消息);否则,服务器则认为这条 QoS1 的消息未送达客户端(是离线消息,下次客户端重连后需要重发)。对于你提到的 zeroMQrabbitmq,他们本身不是实现的 MQTT 协议,是不能与 以 MQTT 协议为基础的服务端 Mosca 对接上的,建议 web 端使用 MQTT.js,安卓端使用 paho 来作为 MQTT 客户端。

  3. MessageId 离线消息都是 随机 ID 的,这是消息的唯一标识,他是通过 shortid 生产的唯一标识串,消息通过 PUBLISH 到一个客户端后,会调用这个 forward 方法(其实就是往TCP 里面写入报文),在写入之前,会根据拿到一个的 messageId,该 ID 是自增长的 Number 类型,且该 ID 不超过 65535,为什么是 0~65535 之间?这取决于可变报头最多容纳的字节数。 。最后,客户端收到服务器发送过来的报文,解析后,客户端必须向服务器返回 PUBACK 报文,该报文必须携带该报文的标识符(即:该消息的 messageId),服务端最后根据 messageId 和 client identifiy 将该消息从离线消息队列中移除,如果未收到 PUBACKPUBACK 报文携带的 messageId 有问题,则导致不能正确更改某一消息的 发送状态 ,这就是 QoS1 为什么会至少发送一次的原因。

你若想详细了解 Mosca 的工作原理,你必须全部明白 MQTT 协议,希望我的答案能给你尽绵薄之力。

回到顶部