V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lsk569937453
V2EX  ›  程序员

现在有个 IM 功能,一个好友下线了,如何让他的好友收到这个通知?(如果服务器挂掉呢?)

  •  
  •   lsk569937453 · 2022-04-11 16:14:14 +08:00 · 2104 次点击
    这是一个创建于 957 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:类似 QQ 聊天,前后端用 websocket 通信(发聊天记录,更新状态)。 问题: 1.如果两个好友 A 和 B 都用手机在线聊天,如果其中一个好友 A 下线了,另外一个好友 B 怎么更新他的好友状态(更新为离线)?如果 A 连接的服务器挂掉了,A 的好友们(手机端)如何更新 A 的状态? 2.两个好友发消息。A 发了:"你好"。B 是怎么获取消息的?服务器推消息到 B 吗?还是 B 主动去拉消息?如果是服务器推消息,A 连接的服务器和 B 连接的服务器不是一台服务器,怎么通知?

    11 条回复    2022-04-11 17:12:35 +08:00
    raycool
        1
    raycool  
       2022-04-11 16:18:57 +08:00
    1. A 下线通知了服务器,服务器告诉 B ,A 下线了,你更新下状态吧。
    2. A 发了你好,服务器接受到了消息,服务器发现是要告诉 B 的,直接推送给 B 。
    macrorules
        2
    macrorules  
       2022-04-11 16:21:52 +08:00
    B 主动去拉比较好,这样就不用占用服务器太多资源
    如果是服务器推消息:
    A -> [A Server]
    A Server 查看目标 B ,看看本地有没有这个连接,如果没有,发送到"路由器"
    路由器广播:谁有 B 的连接啊...
    B Server: B is at 10.11.11.12
    最后 A Server 拿到 B 的所在服务器,记录在缓存里(有 TTL ),下次再找 B , 直接查表
    angryfish
        3
    angryfish  
       2022-04-11 16:27:38 +08:00
    1.离线状态信息可以推拉结合。A 下线的时候,给好友推个信息。B 也可以隔段时间更新下在线列表。
    2.A 、B 不在同一个服务器,你们总是用同一个数据库,或者通过订阅 mq 获取消息吧?
    0o0O0o0O0o
        4
    0o0O0o0O0o  
       2022-04-11 16:33:39 +08:00 via iPhone
    我觉得在线状态是靠心跳包和主动发消息来维护的,一段时间没有动静就是离线了,当然也要提供一个主动离线的接口。然后某个用户状态变为离线也当作一条消息来推送给别的用户。
    twing37
        5
    twing37  
       2022-04-11 16:46:11 +08:00
    1. A-> state service -> B (服务拆分)
    2. A -> MQ -> B 消息队列广播 另外一种: A-> Route GRPC -> B 私信
    涉及的东西有点多.甚至都不知道在哪开始聊
    lsk569937453
        6
    lsk569937453  
    OP
       2022-04-11 16:49:14 +08:00
    @raycool
    1. 用户 A 连接的 A 服务器,用户 B 连接的 B 服务器。此时 A 掉线了,A 服务器怎么通知 B 服务器?
    liuxingdeyu
        7
    liuxingdeyu  
       2022-04-11 16:49:50 +08:00
    一般是心跳维护在线状态,离线了之后给个异步任务,能找到链接 fd 的就直接发,找不到的就找个最近登录的设备发个离线推送(这里要明确推送方式,国内一般兼容 oppo vivo 华为 小米 苹果五个,国外一般税 google 和苹果)。如果挂了,你要看怎么挂,看服务是怎么布的,才能明确解决方案。由于是异步任务,大家面向 broker ,所以几个服务器也无所谓。离线状态的推送本质上来说和你的聊天消息的推送没啥区别,也就是消息定义不一样
    lsk569937453
        8
    lsk569937453  
    OP
       2022-04-11 16:53:57 +08:00
    @macrorules 你的意思是前端每 5 秒定时向后端发送 http 请求拉消息吗?就是说如果 B 有 10000 个好友和 100 个组,B 每 5 秒钟会拉所有好友的消息+好友状态+群消息+群成员状态?
    lsk569937453
        9
    lsk569937453  
    OP
       2022-04-11 16:56:19 +08:00
    @liuxingdeyu A 用 webscoket 连接的是 A 服务器,B 用 webscoket 连接的是 B 服务器,此时 A 掉线了,A 服务器怎么通知到 B 用户?
    liuxingdeyu
        10
    liuxingdeyu  
       2022-04-11 17:06:08 +08:00
    @lsk569937453 用啥连无所谓,但是你连接这块最好就只负责收发,消息处理啥的最好不要和连接耦合起来
    sunjiayao
        11
    sunjiayao  
       2022-04-11 17:12:35 +08:00
    有个点没看明白。服务器 A 和服务器 B 不是组集群么?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1611 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:57 · PVG 00:57 · LAX 08:57 · JFK 11:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.