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

Java 中并发请求多个接口怎样才能效率最高呢?

  •  1
     
  •   noble4cc · 4 天前 · 2187 次点击

    在 Java 中并发的请求多个接口,把请求来的数据做个聚合然后返回,如果是调用了 api1 然后再调用 api2 再调用 api3,这种方式可能大多数时间都在网络 IO 上了,而且随着接口的变多性能不断下降 如果是在 go 中直接用协成就可以了,请求五个 api 和请求一个 api 耗时可能差不多(前提 api 平均耗时都一样)

    java 中该如何编写代码呢?使用线程池的话肯定提高效率有限,因为线程不是协成,数量不会太多,并发量大了都在线程池里排队了

    使用 NIO httpclient 可能效果好些,但是都必须写 callback,怎么判断所有的 api 都把结果成功返回了,然后我们要聚合接口,callback 写起来有些难受

    java 中这种场景应该很多见,一般会怎么处理呢?

    38 条回复    2020-03-30 15:47:12 +08:00
    guyeu
        1
    guyeu   4 天前   ❤️ 1
    线程池+CompletableFuture+聚合操作
    pursuer
        2
    pursuer   4 天前
    使用 Kotlin,C#的 async await,使用 Java Promise 库自己封装或者等待 Project Loom
    guyeu
        3
    guyeu   4 天前
    CompletableFuture 自带一个线程池,自己写的话可能比协程别扭一点,但是效率差不多
    xuanbg
        4
    xuanbg   4 天前
    其实还是前端直接调各个接口拿数据效率高,前端 JS 天然就是异步模式的。
    coer
        5
    coer   3 天前
    callback+CompletableFuture ?
    jamlee
        6
    jamlee   3 天前
    RxJava 比较适合这种事情吧
    areless
        7
    areless   3 天前 via Android
    nginx lua 抗下大半
    Artiano
        8
    Artiano   3 天前
    RxJava zip,用 Kotlin async/await 特别爽
    123444a
        9
    123444a   3 天前 via Android
    肯定是 callback 丫大哥,多线程不需要加锁
    123444a
        10
    123444a   3 天前 via Android
    callback 都是在 io 线程的,然后唤醒工作线程在工作线程判断收完 response 没,然后记得设置超时也要 callback
    CoderGeek
        11
    CoderGeek   3 天前
    Future rx
    araaaa
        12
    araaaa   3 天前 via iPhone
    rxjava spring reactor
    th00000
        13
    th00000   3 天前
    异步可解
    xhinliang
        14
    xhinliang   3 天前
    CountDownLatch
    gz911122
        15
    gz911122   3 天前
    rxjava 了解一下

    或者 kotlin 协程
    Kipp
        16
    Kipp   3 天前 via iPhone
    最近也同样遇到这个问题 mark
    yeqizhang
        17
    yeqizhang   3 天前 via Android
    futuretask 短板是时间最长的那个接口
    liuliuluk
        18
    liuliuluk   3 天前
    以往项目中是用 Future,mark 一下 JDK8 新特性
    micean
        19
    micean   3 天前
    java 的 vertx 可以这么用

    CompositeFuture.all(请求 1,请求 2...)
    .compose(结果集 -> 处理结果集,返回最终结果)
    .setHandler(成功时的处理最终结果,至少一项请求失败时处理异常)

    和 java 自带的 CompletableFuture 相比,只用了 1 个线程,无阻塞。
    mosliu
        20
    mosliu   3 天前
    jdk8
    CompletableFuture allof
    Macolor21
        21
    Macolor21   3 天前 via iPhone
    以前做个类似场景,用创建个线程池,然后用 CountdownLatch 。看楼上似乎 8 的特性也支持。建议楼主写多个版本,做下 benchmark
    noble4cc
        22
    noble4cc   3 天前
    @guyeu 线程池在并发量大的情况下不如协成吧
    感觉线程池的原理是使用多线程进行 http 请求,比如 5 个 api,开 5 线程,然后聚合,但是每个线程在执行的时候 io 是阻塞的,大部分的线程时间都浪费在阻塞上了,如果我们这种聚合 api 数据的请求特别多,比如 1000qps,复用五个线程或者多开点 20 个,相当于 1000 个要请求 5000 次后端 api,在线程池里排队处理的话太慢吧
    tairan2006
        23
    tairan2006   3 天前 via Android
    这不是基本功么,开线程等待完成,CountDownLatch 啊
    Seawalker
        24
    Seawalker   3 天前 via Android
    标记一下看看有没有好方案
    shaoyijiong
        25
    shaoyijiong   3 天前
    一楼标准答案
    yc8332
        26
    yc8332   3 天前
    只是聚合请求,干嘛不搞个现成的 api 网关就好了。。
    piglovesx
        27
    piglovesx   3 天前
    小白一枚,很好奇协程是从哪个英文单词翻译过来的,是 channel 吗?
    guolaopi
        28
    guolaopi   3 天前
    C#:Task.WaitAll();
    (滑稽
    LosLord
        29
    LosLord   3 天前
    CompletableFuture.allOf(List<CompletableFuture>)
    noble4cc
        30
    noble4cc   3 天前
    @tairan2006 老哥我说过多线程方案性能肯定不行
    200 qps 访问 5 个 api 不能开 1000 个线程吧,线程复用一个机器 8core 开 16 个工作线程的话,每次并发的请求后端 api 是 16,每个 api 平均耗时 10ms 的话,第 200 个请求得等到什么时候呢?量少了确实没什么问题,java 类似的工具包确实也多如牛毛
    noble4cc
        31
    noble4cc   3 天前
    @micean 这个本质上确实是 io 多路复用的原理吧,开起来挺方便的,vert.x 不太熟,netty 到是经常用,我一开始想的是用 netty 封装个 httpclient,但是感觉搞起来太麻烦了,是不是 vert.x 就是用 netty 实现了 http 协议了
    lscexpress
        32
    lscexpress   3 天前
    @piglovesx Coroutine 翻译为协程,通常来说 java 不用协程。channel 在书中的翻译多为信道或者通道
    piglovesx
        33
    piglovesx   3 天前
    @lscexpress 谢谢 :)
    guyeu
        34
    guyeu   3 天前
    @noble4cc #22 是的,线程池在并发量大的情况下不如协程。所以这种情况下会做一些设计,比如把发消息和收消息分开,一个线程池专门发,一个线程池专门处理收消息,也就是 NIO 的思路。。
    hpeng
        35
    hpeng   3 天前 via iPhone
    看一楼的
    aguesuka
        36
    aguesuka   3 天前 via Android
    @noble4cc vertx 底层就是 netty
    buliugu
        37
    buliugu   3 天前
    java 大量 API 请求可以用 Quasar,现成的纤程库
    elevation
        38
    elevation   2 小时 12 分钟前
    不知道你现在怎么样,我觉得用 diruptor,环形数组线程分发,可以降低消耗,自己写底层实现,工厂,资源调用。比较方便;
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4011 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 09:59 · PVG 17:59 · LAX 02:59 · JFK 05:59
    ♥ Do have faith in what you're doing.