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

Java http 请求中如何处理外部回调?

  •  1
     
  •   wangsongyan · 2021-06-23 14:03:41 +08:00 · 2736 次点击
    这是一个创建于 1244 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的服务(A)部分功能依赖于外部服务(B),A 向 B 发送 http 请求时,B 会立即返回“提交成功”,等 B 处理完成后才会回调 A 返回我想要的数据。
    B 服务不具备修改为同步返回的条件。 当用户访问 A 时,我想返回 B 回调的结果,请问怎么实现? 目前想到两种方式:

    • 1.在 A 请求 B 过程中,A 阻塞等待 B 返回结果,然后返回用户。
    • 2.A 请求 B 后直接返回用户结果,然后用户再使用轮询方式从 A 获取结果。

    或者还有没有其他更好的方式?写惯了同步代码,现在换种方式不知道咋搞了

    第 1 条附言  ·  2021-06-24 11:04:00 +08:00

    感谢各位大佬出谋划策,汇总下解决方案:

    1. A使用阻塞的方式直到获取到B的回调才返回
      • 逻辑简单,变异步为同步
      • 响应时间不确定,影响用户体验
    2. A调用完成后直接返回用户“提交成功”,之后由用户侧进行轮询
      • 响应迅速,实现简单
    3. A调用完成后直接返回用户“提交成功”,B回调后通过http2/websocket方式通知用户侧
      • 响应迅速
      • 实现难度较2大
    18 条回复    2021-06-24 13:51:23 +08:00
    uselessVisitor
        1
    uselessVisitor  
       2021-06-23 14:09:05 +08:00   ❤️ 1
    B 是异步的呗?方法 1 吧,连接不断等着 B 返回真正的结果
    hdiwhsg
        2
    hdiwhsg  
       2021-06-23 14:09:54 +08:00   ❤️ 1
    建议用户轮询方式获取结果
    illuz
        3
    illuz  
       2021-06-23 14:10:18 +08:00 via Android   ❤️ 1
    1 用户体验不行,一般用轮询。
    如果执行结果 A 需要记录,不要等用户端轮询再去调用 B,最好还是在 A 服务器自己做轮询,这样用户响应也比较快。
    dbpe
        4
    dbpe  
       2021-06-23 14:12:33 +08:00   ❤️ 1
    (业务上一定要同步的堵塞住么?优雅点不应该是消息通知么
    yitingbai
        5
    yitingbai  
       2021-06-23 14:13:24 +08:00   ❤️ 1
    如果时间就几秒钟建议用方法 1, 这样逻辑也简单
    hdiwhsg
        6
    hdiwhsg  
       2021-06-23 14:14:00 +08:00
    如果非要做成同步的也不是不行,可以把用户轮询改成 A 系统替用户轮询,具体怎么轮询?
    1.A 系统调用 B 系统的接口之后,可以去轮询一个 redis 的占位符。
    2.B 系统回调 A 系统的过程中,A 系统的逻辑就是更新这个占位符,把占位符的状态更新成已有结果。
    3.第一步的逻辑这时候就轮询到这个占位符的状态是已有结果,就可以返回给用户了
    Puteulanus
        7
    Puteulanus  
       2021-06-23 14:24:20 +08:00   ❤️ 1
    轮询吧,类似接入第三方支付的,虽然也可以支付成功之后那边回调这边,不过我看他们文档好像都写的这种不保险,建议自己轮询支付状态,至少混合
    ikas
        8
    ikas  
       2021-06-23 15:30:30 +08:00   ❤️ 1
    你这个其实与 b 没有关系,如果 A 提供的一个长时服务,也会这样.
    1.可以用轮询通知
    2.可以用 http2 推送
    3.A 使用使用异步连接,当 A 拿到数据后,找到其对应的连接,写回,这种一般我们做设备相关连接经常用
    jeffxjh
        9
    jeffxjh  
       2021-06-23 18:31:26 +08:00   ❤️ 1
    websocket 你值得拥有
    LuckyLight
        10
    LuckyLight  
       2021-06-23 20:37:55 +08:00   ❤️ 1
    用户和服务 A 之前使用长轮询,服务 A 收到服务 B 的回调后返回给用户结果
    Jirajine
        11
    Jirajine  
       2021-06-23 20:48:53 +08:00 via Android   ❤️ 1
    一般来说由用户端轮询,因为网络环境不确定,各种推送通知不一定可靠。
    rockyliang
        12
    rockyliang  
       2021-06-23 23:21:28 +08:00   ❤️ 1
    不建议使用第一种方法,假设 B 服务回调需要等 1 分钟,难道你要用户在那里干等 1 分钟什么事情都不能做吗,体验太差了,而且时间拖太久的话,也会引发前端超时
    strawberryBug
        13
    strawberryBug  
       2021-06-23 23:32:20 +08:00 via Android   ❤️ 1
    你们没有中间件吗? B 处理完发 mq,A 订阅 ma 拿处理结果,好处就是解耦,后续接入其他服务直接订阅消息就行。或者 B 处理完直接回调 A 的接口
    nvkou
        14
    nvkou  
       2021-06-24 08:41:13 +08:00 via Android   ❤️ 1
    跟 b 没关系
    a 阻塞客户不现实。直接返回提交成功就是
    回调来了再推送通知或更新状态等用户下次查询

    为啥非要及时主动给用户信息,这是业务问题吧。跟查快递一样
    zifangsky
        15
    zifangsky  
       2021-06-24 10:01:21 +08:00   ❤️ 1
    websocket 的典型用途
    wangsongyan
        16
    wangsongyan  
    OP
       2021-06-24 10:46:50 +08:00
    @beichenhpy #1 B 是异步的,处理完后回调 A 。这种方式逻辑最简单,达到了异步变同步的效果,但是确实会有楼下说的问题,阻塞时间不确定,影响体验。

    @dbpe #4 不一定是同步,达到效果就行,综合下来看 websocket/http2 推送是个不错的选择。

    @hdiwhsg #6 这个确实是最直接的方式,我先试试。

    @rockyliang #12 我确实忽略了还有这种情况了。

    @strawberryBug #13 因为 B 是外部服务,不受我控制,现在确实也是 B 处理完以后回调 A 的。

    @nvkou #14 同步方式写代码先入为主了,我的思路有问题。
    a719031256
        17
    a719031256  
       2021-06-24 13:50:44 +08:00
    这里的用户体验应该是指用户想获取到的服务,而不是响应速度
    正确的做法我认为应该按 1 来处理是很合适的,等待信息的过程可以让前端做得更漂亮点就行
    shangfabao
        18
    shangfabao  
       2021-06-24 13:51:23 +08:00
    @hdiwhsg 是个方案,用户查询的时候去查 redis 处理也是可以的,消耗也比较少
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6078 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 06:22 · PVG 14:22 · LAX 22:22 · JFK 01:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.