Java http 请求中如何处理外部回调? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wangsongyan
V2EX    Java

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

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

    我的服务(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
    zm8m93Q1e5otOC69
        1
    zm8m93Q1e5otOC69  
       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     Solana     909 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 20:59 PVG 04:59 LAX 12:59 JFK 15:59
    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