IM 中如何处理节点故障,导致消息不可靠问题?请教

2023-02-17 19:54:54 +08:00
 xhldtc

最近在做一个 IM 的开发,初次尝试 IM 开发,碰到点问题向懂这块的兄弟们请教一下。直接上图: 先简单说一下技术方案吧:

现在问题是,假如说某台机器故障了,比如假设 MAC_3 故障,硬件损坏,那 MQ 中 MAC_3 Topic 中的消息会越积越多,而这个 Topic 又没有订阅者,那这部分信息该怎么处理?

1796 次点击
所在节点    程序员
20 条回复
Nazz
2023-02-17 20:01:11 +08:00
做好容灾就行了
billlee
2023-02-17 20:03:24 +08:00
应该用 userId 的 hash 来分区。哪有人用服务器的地址分区的。
wyx119911
2023-02-17 20:14:14 +08:00
这架构很难维护,服务应该做成无状态的
KristenGe
2023-02-17 22:24:21 +08:00
@Nazz 问题是一旦量上来了,扩缩容的时候,可能会出现多台主机对应的 MQ Topic 处于无订阅状态。
KristenGe
2023-02-17 22:26:14 +08:00
@billlee 能具体点吗?目前 MQ 中的消息等于是通过 userId 寻址,找 Topic 送达对应主机,userId 分区是怎么个做法?
KristenGe
2023-02-17 22:27:28 +08:00
@wyx119911 服务如果无状态,消息寻址,或者说消息路由吧,怎么送达对方的 channel 呢?
Nazz
2023-02-17 22:49:33 +08:00
@gemingsy im server 应该是有状态副本集, 把用户分配到固定的节点上.
KristenGe
2023-02-17 23:16:38 +08:00
@Nazz 这个其实没有问题的,无非就是 client 和 server 之间做一层 routing ,现在问题是不同节点上的用户之间消息交互,是通过对方机器标识(或服务标识)做 MQ 的 Topic ,精准送达,如果服务 down 了,topic 成无订阅状态,消息无法消费了。现在能想到的是用 ZK ,不过前期不想太复杂。
javapythongo
2023-02-17 23:41:04 +08:00
可以把用户是否在线存储到 redis 中,发送消息前,判断下,不在线就直接离线存储
b1ghawk
2023-02-17 23:41:06 +08:00
可以把消息泛播到每个服务器上,
每个服务器判定这条消息的用户是否在本机上又连接,有的话就发出去。
huanw
2023-02-17 23:51:11 +08:00
楼上的老哥说得对,消息应该散播到集群每个节点上,因为你每个节点都有 SessionMap ,由节点来决定怎么给客户端发消息。做到无状态才有利于扩展,比如断线重连,本来连接节点 1 ,断线后连接节点 2 ,这都不影响消息发送。
mawerss1
2023-02-18 00:02:07 +08:00
不说这个系统设计如何,单论这个问题,在你这个设计里挂了消息就只能扔掉,如果丢消息,你需要在发送端做好存储
KristenGe
2023-02-18 01:40:34 +08:00
@b1ghawk 这种做法我感觉在 IM 的系统中不太现实,量一旦上来了,会造成网络堵塞;而且每台机器都等于要处理全网的消息量,性能一定会成为瓶颈
KristenGe
2023-02-18 01:48:38 +08:00
@mawerss1 发送端其实已经收到消息发送成功的应答了,因为消息已经落到 MQ 里了
Nazz
2023-02-18 07:29:15 +08:00
@gemingsy 服务挂了让副本起来工作啊,每个编号的 Deployment 搞多个 Pod ,订阅同一个主题
Nazz
2023-02-18 07:56:52 +08:00
@Nazz 小集群内做成无状态服务
PythonYXY
2023-02-18 11:08:55 +08:00
路由信息单独保存在 redis 或者 kv 数据库中,抽象出一个路由服务集群统一消费 MQ 消息,对消息进行路由推送。不过要考虑路由服务的消费能力,避免过高的消息延迟。
NUT
2023-02-18 11:23:57 +08:00
通用问题。 其实必须有一个主去做 session 状态的分配。 陌陌老早时候有一个 ppt 分享他们的策略。 分三层,一层是接入层, 无状态,可以任意扩展,主要是接受链接, 第二层 逻辑层,保证消息业务逻辑的路由等, 第三层存储。

其实你的服务没有脑子,需要有一个脑子,去做这种订阅关系的维护, 也就是 接入层上线以后, 由 master 去做分配 session 相关策略。主要保证 master 强一致就行。

不过咋说,难度就会上一个层级。 还可以看看 codis 还有 tidb 等分布式设计。 会有帮助的。
guonaihong
2023-02-18 17:14:12 +08:00
收藏下下。。。
KristenGe
2023-02-19 16:16:54 +08:00
@NUT 如果有接入层,单论接入层的话,像连接的 channel 这种东西是作为集群各个节点本地 session 存储,还是用序列化方式统一存储,channel 这种东西适合做序列化统一存储吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/917029

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX