搜索了一些资料, 感觉应该可以做。
推送服务用nodejs+socket.io
做, 记录在线用户和离线消息交给redis
。
一对一, 客户 A
给客户 B
推消息。 客户 B
不在线。 记录到redis
中。 并且做持久化防止丢失。
但是一对多, 有点懵。 客户 A
给广播给所有人。 在线的兄弟直接转发,
不在线的兄弟们, 我怎么知道有那些。 并且给他们记录离线消息
呢?
必须完整的把当前
所有用户的 uid 查出来, 预存到redis
。 在线用户发了出栈。 剩余全部存离线消息?
或者一开始查询出所有用户 uid, 存起来, 在线的用户修改状态, 非在线的存离线消息。 如何做到和数据库里的成员
表同步呢? 毕竟每分钟都可能发生注册。
这两天对这类东西很感兴趣, 想试着做一个。 想不通, 请各位大佬解答。
1
edk24 OP 辛辛苦苦的 md 标注, 没了! 变得更难阅读了。。。
|
2
edk24 OP 我这个需求可能不太像 push server, 倒是像个聊天。 哈哈 概念还没搞清楚呢
|
3
baojiweicn2 2019-07-15 01:30:55 +08:00 via Android
mqtt。qos 2
|
4
wd 2019-07-15 05:57:59 +08:00 via iPhone
push 和 聊天本来就有点共通。你这个需求是离线消息的处理逻辑,一个群发消息是需要给所有要收消息的人都记录一份的,然后一般是用户下次链接的时候发给用户。
|
5
gzlock 2019-07-15 06:39:26 +08:00 via Android
用时间流的概念就可以解决了吧
一个聊天群组一个 ID,所有聊天内容都有时间信息,都存到数据库,a 在 22 点下线,记录下线时间,按 a 的下线时间查询数据库就能获取到哪些内容需要推送给 a |
6
Yourshell 2019-07-15 07:52:31 +08:00
重点是客户端的实现吧
|
7
phpdever 2019-07-15 08:53:16 +08:00
利用长连接状态即可。
记录用户的 uid 及长连接 id,在建立长连接,断开长连接时进行持久化存储,再进行信息消息推送。 但需要考虑极端情况下的断线重连等问题。 用户在线不在线其实并不需要关心,推送消息时,如果在线,只要通知客户端进行拉取最新的消息即可,如果不在线,上线之后主动拉取。 如果是是一对一进行推送,需要同时推给自己和对方,如果是一对多,则推送给所有群组成员。 难点其实在于客户端处理,你可能还需要用到消息队列,如:rabbitmq。 |
8
opengps 2019-07-15 09:00:39 +08:00
轮训不可取,长连接需要踩够坑才可行
|
9
Universe 2019-07-15 10:27:34 +08:00
这样说不大看得出架构,就假设是服务端和客户端,服务端负责控制消息分发,客户端向服务端发出生产和消费请求。
那么有一个区别,服务端在分发消息的时候是主动还是被动,像 flume 就是设置 sink 主动推送,而 kafka 服务端就是被动被客户端请求消费推送。 像 kafka 这类被动推送就比较好处理,kafka 的做法是记录不同消费者的偏移量,消费者每消费一条数据就把偏移量向后推一条,这样就不需要关心消费者是否在线。 像 flume 这类其实对于内部 channel 到 sink 也是被动推送,而 sink 是主动消费 channel 并主动推送出去,所以在外部看起来是个主动推送。 那么在这里就能看出来,其实主动还是被动并不是关键,记录不同客户的偏移量才是关键,如果你希望被动推送,那就让客户端请求推送,如果你希望主动推送,那就在客户端链接上的时候从服务端请求推送。 现在看你的 3 个问题: 1. 使用 offset 记录推送进度,离线用户的 offset 不会变化,不需要另外记录离线消息。 2. 这个推送方式是主动推送,只推送在链接的用户并调整偏移量。 3. 新用户直接给最后的 offset,是否在线就是是否有链接。 使用 offset 就还有问题需要考虑: 1. 每条消息需要一个唯一 id 来作为偏移量,这个唯一 id 怎么取 2. 如果离线用户长期不消费离线数据造成离线数据堆积,这部分数据是进行持久化还是删掉 3. 一致性是否需要保证,重复推送是否需要避免 4. 根据上一个问题的结果来决定推送数据粒度是批量还是单条 |