微信/钉钉里, 用户可以任意建群聊天, 这是怎么实现的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
melonux
V2EX    程序员

微信/钉钉里, 用户可以任意建群聊天, 这是怎么实现的?

  •  
  •   melonux 2020-09-16 16:42:47 +08:00 4329 次点击
    这是一个创建于 1901 天前的主题,其中的信息可能已经有所发展或是发生改变。
    教科书上写, 让客户端使用 MQTT 做订阅. 订阅的 topic 就是 群名字 . 原理上是没问题. 可是几年用下来, 大大小小的群能够上千个了, 好多都很久没有发言了. 如果往这种僵尸群中发言, 群成员还是能立刻收到消息. 那就意味着, 一个用户要一直订阅着上千个群了. 这会非常消耗 MQTT broker 的资源吧. 业界都是怎么解决的呢?
    13 条回复    2020-09-17 00:38:26 +08:00
    0x0x
        1
    0x0x  
       2020-09-16 16:46:24 +08:00
    不用 MQTT
    melonux
        2
    melonux  
    OP
       2020-09-16 17:01:20 +08:00
    @ck19920702 那用什么? 不管是啥, 也得订阅吧. 只要订阅, 就涉及那么多群是否都要一直订阅着的问题.
    joesonw
        3
    joesonw  
       2020-09-16 17:20:15 +08:00
    发言的时候推到每个人自己的 topic?
    CloudnuY
        4
    CloudnuY  
       2020-09-16 17:27:40 +08:00
    群绑定用户,用户不绑定群,新建的群拉进去之后不发言 被拉的人是看不到的
    pengjay
        5
    pengjay  
       2020-09-16 17:33:35 +08:00
    群消息通知每个用户一个公用 topic 。进群聊界面才开始订阅群的 topic,离开群就取消订阅。
    GM
        6
    GM  
       2020-09-16 17:35:34 +08:00
    客户端和服务器保持一个连接,几个活跃用户就几个连接,这个是必须的,现阶段已经很成熟了,不是难题了。
    然后服务器维护群和群员关系,这里要尽量用紧凑高效的数据结构。
    当群有新消息,服务器通过群员关系,遍历出所有需要发消息的群员,通过第一步建立的长连接发出去。

    就这样,任务结束。
    kop1989
        7
    kop1989  
       2020-09-16 17:41:29 +08:00
    我的理解是群里面包含成员字段。
    既有一个群表。里面有群 id/code 、 群名称、群组成员 id 。
    然后当一个人发消息之后。
    相当于是对此群 id 讲话。

    然后通过群 id 查询群组成员 id 。再通过群组成员 id 查询当前的在线状态决策如何同步消息。
    如果当前活跃则走 websocket/长轮询 /tcp,辅以推送透传消息作为保底手段。通知客户端有新的消息,然后客户端发起信息同步。
    当前用户不活跃则直接发送系统级 notification,待用户唤起 app/应用再由客户端发起信息同步。
    kop1989
        8
    kop1989  
       2020-09-16 17:43:20 +08:00   1
    换句话说,群也是一个“用户”,只不过这个用户包含有多个真正的用户。然后几个用户之间都是在和这个叫“群”的用户交流。
    opengps
        9
    opengps  
       2020-09-16 17:58:03 +08:00 via Android
    你为什么非要用 topic 的原理来实现群聊呢?
    我完全可以用传统关系型数据库给你,所有群内成员遍历发送一遍来实现,这个原理你理解下
    Code418
        10
    Code418  
       2020-09-16 18:39:43 +08:00   1
    以前用 MQTT 搞过,不过最终的感觉是其实 IM 用 MQTT 实现还是挺麻烦的,我不是专门作 IM 的,这部分也是菜,只能讲一些粗浅的地方。其实上面大家都讲的差不多了。

    群或私聊本身有自己的 topic,但事实上在客户端进入聊天时再订阅就好,关键在用户需要一个随连线一起订阅的 notify 用的自己的 topic,连上 broker 就必定订阅这个,往这里面 notify 就好。反正你消息包定义定好了你想通知什么都可以。

    重点在 notification 的设计上怎么作高效。可以实时发 notify,单纯做到这步的话实现很简单。但是一个群就得先捞完所有群员然后各自发的话,无论是 dispatch 或是实际的 I/O,人多群多的情况下就会非常吃重,这部分看实际业务状况跟想怎么去设计权重与优化。不过单纯用 MQTT 的机制做起来我觉得挺麻烦困难的,本身的使用场景其实就不是常规的 Chatting 。

    尤其 IM 还要考虑到实际的离线消息,就更加复杂麻烦跟炸性能。反正我做到这边我就扔着等有时间再优化了,还没时间拆人家的 IM 抄袭(划掉)琢磨人家的设计跟优化……
    Bijiabo
        11
    Bijiabo  
       2020-09-16 18:48:57 +08:00
    一般 MQTT 会配合规则引擎使用,用户加入哪些群,在云端可以通过规则引擎将消息聚合到一个用户的 topic 中
    也就是说,用户订阅一个消息 topic 就足够了。
    neoblackcap
        12
    neoblackcap  
       2020-09-16 19:11:51 +08:00
    没记错的话,微信是参考微软的 Exchange ActiveSync 。用 mqtt 硬套不了。同时最开始的那版好像是基于 xmpp 的
    zjyl1994
        13
    zjyl1994  
       2020-09-17 00:38:26 +08:00 via Android
    肯定不能每个会话一个 topic 的,你把群理解为特殊的用户就行了。有人在群里发消息,触发一个遍历群成员挨个写入推送渠道的动作就可以了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     839 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 19:33 PVG 03:33 LAX 11:33 JFK 14:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86