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

如何合适地用消息队列做查询接口

  •  
  •   awesomelei · 2020-08-27 15:52:56 +08:00 · 2015 次点击
    这是一个创建于 1542 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现有老大需求, 原先同步的接口改为异步的基于消息队列改造的接口, 这意味着一个原先的查询接口不能实时地返回数据, 现在问题是,前端查询页面是否得定时去抓未来可能的查询结果?是否得 ajax 轮询才能实现?

    15 条回复    2020-08-28 14:09:26 +08:00
    opengps
        1
    opengps  
       2020-08-27 15:55:15 +08:00
    用消息队列提供查询结果??这个操作有点迷,你怎么确定 A 查询的结果 不是从队列里消费的 B 的查询结果?
    rainbirda
        2
    rainbirda  
       2020-08-27 15:59:05 +08:00 via Android
    可以开个 websocket,等消息队列消费后,向 websocket 返回数据,应该是可行的
    killergun
        3
    killergun  
       2020-08-27 16:01:58 +08:00
    看对实时性的要求,没有要求就轮询呗,有的话就需要实时通知了
    awesomelei
        4
    awesomelei  
    OP
       2020-08-27 16:05:26 +08:00
    @opengps 生产的时候加个唯一字段, 然后消费的时候带上这个字段值来保证对应关系,哈哈哈
    littlewing
        5
    littlewing  
       2020-08-27 16:05:35 +08:00 via iPhone
    异步也不需要消息队列啊
    awesomelei
        6
    awesomelei  
    OP
       2020-08-27 16:06:11 +08:00
    @opengps 就是一个老接口改成 2 个消息系统 topic, 一个请求, 一个响应
    dzdh
        7
    dzdh  
       2020-08-27 16:09:48 +08:00
    输出任务 id 然后轮询 id 结果?
    kiracyan
        8
    kiracyan  
       2020-08-27 16:11:13 +08:00
    看你业务咯 有实时要求就 Websocket 没有就轮询
    opengps
        9
    opengps  
       2020-08-27 16:19:24 +08:00
    @awesomelei 你消费了之后,比如说 A 消费了 B,那么 B 再去消费的时候就没有 B 的结果了
    676529483
        10
    676529483  
       2020-08-27 16:36:16 +08:00
    感觉应该是基于缓存去查询,基于消息队列去同步变化的数据
    Rush9999
        11
    Rush9999  
       2020-08-27 16:37:59 +08:00
    Varobjs
        12
    Varobjs  
       2020-08-27 17:06:05 +08:00
    这样搞?
    ------------------------------------------------------------------
    接口每次查询缓存是否有数据
    有:直接返回
    没有:发送刷新缓存的消息,返回空?

    消息消费进程收到消息,请求 db | api 获取数据,丢进缓存
    ------------------------------------------------------------------
    xuanbg
        13
    xuanbg  
       2020-08-27 17:57:04 +08:00
    在接口响应特别慢的前提下,是应该先返回一个任务 id,然后用这个 id 轮询另一个接口获取数据。
    oneisall8955
        14
    oneisall8955  
       2020-08-27 22:50:13 +08:00 via Android
    额,我司用的骚操作。整个流程如下:前端 A 调用后端 B,B 后端发异步消息给 C,C 接口很慢,C 有结果再异步发回给 B 。A 如何得到结果呢,前端说不能 ajax 轮询,也不能用 websocket,又不允许 B 阻塞

    目前解决办法是:A 分两次请求,第一次请求使用 requestId 请求 B 的预查询接口,B 用消息中使用这个 ID 发消息给 C,C 结果消息再返回这个 ID,B 得到结果存带过期时间的缓存。

    A 发完第一次请求后立即使用 ID 请求 B 的获取结果接口,B 用谷歌的重试库,10 秒内自动随机 10 次从缓存中获取结果,获取不到就是失败。

    重试次数和时间都需要按照业务来估计,觉得这个方案还是很复杂。。。说到底第二次请求 B 也阻塞最多 10 秒了吧只是自动重试而已
    no1xsyzy
        15
    no1xsyzy  
       2020-08-28 14:09:26 +08:00
    @opengps #1 #9 转 token-based CPS 就行了,A 根本消费不到 B,甚至不知道还有 B
    实践上可以是单独设置 topic,或者根据每个前端设置 topic

    @awesomelei #0 经典四种:轮询、长轮询、SSE 、WebSocket
    opendota 的分析请求就是轮询。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2527 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:53 · PVG 23:53 · LAX 07:53 · JFK 10:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.