前端新消息提示,这样实现的思路是对的吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
movq
V2EX    前端开发

前端新消息提示,这样实现的思路是对的吗?

  •  
  •   movq 2022-02-03 15:51:48 +08:00 3871 次点击
    这是一个创建于 1429 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的想法是这样的:

    如果有给这个用户的新消息,先把具体内容存到数据库,然后把有新消息的通知进入 rabbitmq 队列

    如果此时用户在线,直接发送到前端(只是通知前端消息数目+1 ,不发送具体消息内容)

    如果用户不在线,就先放在队列里面。用户前端上线后,和后端建立 websocket 连接,然后后端就把队列里面积累的东西发过去

    用户点击消息提示之后,再从后端查询数据库,得到所有的新消息的具体内容

    这样做有什么问题吗?业界通常的做法是什么?

    12 条回复    2022-02-04 14:28:00 +08:00
    ktqFDx9m2Bvfq3y4
        1
    ktqFDx9m2Bvfq3y4  
       2022-02-03 18:47:49 +08:00   1
    如果让我做,那么:

    新消息来后直接入 RabbitMQ ,防止消息太多数据库压力大。Consumer 负责将数据入库,同时判断用户是否在线,在线就发给用户,不在线就标记最新版本号。

    用户上线后先通过 API 获取最新版本号,如果有未读消息则同时获取消息内容。之后再建立连接开始接收新消息。
    ktqFDx9m2Bvfq3y4
        2
    ktqFDx9m2Bvfq3y4  
       2022-02-03 18:59:39 +08:00   3
    但如果是给后台用,而且用户量不大,能接受若干秒延迟,则可以直接使用 HTTP 而不是 Websocket ,每隔一段时间比如 30 秒请求一次即可。是否有最新消息这个标记保存在 Redis 中。

    我的后台应用就是这么弄的,配合 Long Polling 实在秒提醒。
    liuzhedash
        3
    liuzhedash  
       2022-02-03 21:03:52 +08:00
    早年论坛实现都是轮询,数据库压力没有那么夸张。
    当然,这个只适合站内信的场景,不适合高频率的 IM 对话那种。
    LeeReamond
        4
    LeeReamond  
       2022-02-03 21:23:08 +08:00 via Android
    @Chad0000 轮训和 ws 的开销怎么说,30s 轮训一次开销比 ws 高多少?
    chendy
        5
    chendy  
       2022-02-03 22:24:53 +08:00
    隔壁 sf 的这个帖子是楼主发的么 https://segmentfault.com/q/1010000041363597
    这问题不知道具体业务场景不好说啊
    kaneg
        7
    kaneg  
       2022-02-04 00:08:15 +08:00
    如果有用户一直不上线,消息就一直存在 mq 里?如果有大量类似场景,mq 就会由大量消息堆积而挂掉
    jinliming2
        8
    jinliming2  
       2022-02-04 00:44:50 +08:00   1
    你的消息队列里存的是消息通知,而不是消息内容??
    用到消息队列,应该是缓解数据库那边的压力吧?如果你的消息可以直接入数据库,那应该没必要用消息队列了?新消息来了先写数据库,然后判断用户是否在线,在线的话就推一条新消息通知,用户阅读的时候再查数据库获取数据。
    如果消息量比较大的话,就先把消息放到消息队列,消息入队的时候不通知用户,队列直接输出对接到数据库入库。写完数据库再判断用户是否在线,在线推送。

    至于轮询和 websocket 的选择,看具体的业务实时性:1 、实时性要求非常低,那么完全可以不推送,用户刷新的时候获取新消息( V2EX 貌似就是这个模式),2 、web app ,用户很少会刷新页面,而实时性要求不高的话,用轮询 30 秒、1 分钟,3 、要求实时性高的场景,则使用 websocket ,几乎是实时的。
    轮询需要接口能够承受住刷新请求,websocket 需要服务端能够持有足够多的 socket 连接。
    至于 #6 的 push 消息,使用场景不太一样,主要用于用户没有访问你的网站时也可以收到通知推送(类似于手机 APP 的后台被杀掉,也还是可以通过 FCM/APNs 收到实时推送消息)。你需要注册一个 service worker ,然后用户不需要打开你的网站也可以收到消息推送(只要浏览器在运行,sw 就能在后台接收消息推送),消息推送的形式是通过浏览器的 notification 弹窗(用户必须先授权弹窗)。
    ktqFDx9m2Bvfq3y4
        9
    ktqFDx9m2Bvfq3y4  
       2022-02-04 01:58:45 +08:00 via iPhone
    @LeeReamond #4 ws 主要是开发变得复杂以及服务器能承载的 ws 数量有限(只看过相关文章没有测试过)
    3dwelcome
        10
    3dwelcome  
       2022-02-04 04:52:48 +08:00
    websocket 在安卓上有很大的坑,因为设计上是多线程的。有时候 webview 生命周期结束了,websocket 还挂在后台。

    如果仅仅是 PC 上应用,个人感觉轮询和 websocket 都差不多,两者没啥太大区别。
    zqx
        11
    zqx  
       2022-02-04 11:15:26 +08:00 via Android
    业界常见做法就是前端轮询,后端直接从 mysql 分页查,没有消息队列,也不需要推送。
    movq
        12
    movq  
    OP
       2022-02-04 14:28:00 +08:00
    @chendy 是我发的,场景就是 web 论坛里面私信提醒之类的,感觉也不需要多大的实时性
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2391 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 95ms UTC 10:21 PVG 18:21 LAX 02:21 JFK 05:21
    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