• 请不要在回答技术问题时复制粘贴 AI 生成的内容
luxinfl
V2EX  ›  程序员

面试碰到一个问题,搞不定

  •  
  •   luxinfl · Dec 16, 2020 · 8320 views
    This topic created in 2149 days ago, the information mentioned may be changed or developed.
    比如说要调用 abcde 这五个微服务,调用 b 的前提是先调用 a,cde 没有这种顺序要求。最终数据要求整合。怎么才能让时延变小??
    44 replies  •  2020-12-23 14:08:26 +08:00
    Yoock
    Yoock
    Dec 16, 2020
    1
    waitgroup
    luxinfl
    luxinfl
    OP
    Dec 16, 2020
    2
    @Yoock 有 java 的实现么
    fanyiaa
    fanyiaa
    Dec 16, 2020 via Android
    3
    c#里用 task 很容易。java 不知道有什么简便方法
    Cbdy
    Cbdy
    Dec 16, 2020❤️4
    4
    let resultA
    const [resultB, resultC, resultD, resultE] = await Promise.all([a().then(ra => { resultA = ra; return b() }), c(), d(), e()])
    Yoock
    Yoock
    Dec 16, 2020
    5
    搜到一个 [CountDownLatch]( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)
    不太了解 Java,你看一下
    luxinfl
    luxinfl
    OP
    Dec 16, 2020
    6
    我想说的不是 AQS 方面的东西。是侧重于 java 微服务相关的
    pkwenda
    pkwenda
    Dec 16, 2020
    7
    比如 zuul 网关应该可以写 groovy 从注册中心获取微服务,先调用啊,并发调用 cde,代码整合
    kong 这种可以写 lua 插件
    是这个意思吧,不进行并发处理延时是一样的
    网关做 merge
    mango88
    mango88
    Dec 16, 2020
    8
    可以用几个 future,然后用 CompletableFuture.allOf() ,等所有 future 完成再去组装数据
    xizismile
    xizismile
    Dec 16, 2020 via Android
    9
    去看看 CompletableFuture 类
    hangszhang
    hangszhang
    Dec 16, 2020
    10
    Java 的话, CompleteFuture 或者 RxJava 或者 Future
    DoctorCat
    DoctorCat
    Dec 17, 2020
    11
    看起来是架构方案题,不是编程细节吧。b 调用 a,并降低时延,意味着 b 与 a 的调用链路最短+系统状态保持最优啊。如果分别部署在不同实例,那最好 b 与 a 同一个机架同一个子网,物理距离和网络逻辑位置最短的原则。
    数据聚合最好设计一个数据聚合层比如引入 MQ 而且最好是 pubsub 机制……保持 tcp 长连接替代 HTTP 等等,还有 kernel 网络相关的调优、系统进程 CPU 亲和性的调优等等。
    beidounanxizi
    beidounanxizi
    Dec 17, 2020
    12
    @luxinfl go 的 waitgroup Java 的 countdownlatch 都可以实现 ,
    carlclone
    carlclone
    Dec 17, 2020 via Android
    13
    这题难道不是考察分布式事务吗,楼上的都在讲什么乱七八糟的
    noogler67
    noogler67
    Dec 17, 2020 via iPhone
    14
    时延的话,就是同时发起 acde,等完成后再发起 b
    anthow
    anthow
    Dec 17, 2020
    15
    整几个 CompletableFuture
    Peachl
    Peachl
    Dec 17, 2020❤️1
    16
    @carlclone 分布式事务是保证事务的 明显这个位置问的是如何做到顺序性的 completableFuture 就是正解
    blessyou
    blessyou
    Dec 17, 2020
    17
    js 的话大概是 Promise.all()
    TonyYOYO
    TonyYOYO
    Dec 17, 2020 via iPhone
    18
    @fanyiaa 你可笑死我了
    liuhuan475
    liuhuan475
    Dec 17, 2020
    19
    Future
    sonice
    sonice
    Dec 17, 2020❤️4
    20
    ```
    CompletableFuture<String> futureAb = CompletableFuture.runAsync(() -> {
    // no operation
    }).thenApply(b-> "ab");

    CompletableFuture<String> futureC = CompletableFuture.supplyAsync(() -> "c");
    CompletableFuture<String> futureD = CompletableFuture.supplyAsync(() -> "d");
    CompletableFuture<String> futureE = CompletableFuture.supplyAsync(() -> "e");

    String collect = Stream.of(futureAb, futureC, futureD, futureE)
    .map(CompletableFuture::join)
    .collect(Collectors.joining(" "));

    //output: ab c d e
    System.out.println(collect);
    ```
    Cbdy
    Cbdy
    Dec 17, 2020
    21
    我是 4L,我把原先的 JS 版改成 Java 版
    var resultList = Stream.of(CompletableFuture.supplyAsync(() -> a()).thenApply(ra -> Stream.of(ra, b())),
    CompletableFuture.supplyAsync(() -> c()),
    CompletableFuture.supplyAsync(() -> d()),
    CompletableFuture.supplyAsync(() -> e()))
    .map(CompletableFuture::join)
    .flatMap(it -> it instanceof Stream ? ((Stream<?>) it) : Stream.of(it))
    .collect(Collectors.toList());
    gmywq0392
    gmywq0392
    Dec 17, 2020
    22
    回调
    dddz97
    dddz97
    Dec 17, 2020
    23
    感觉想问的点是 MQ 之类的
    shyrock
    shyrock
    Dec 17, 2020
    24
    插眼等有效回答。
    qiaobeier
    qiaobeier
    Dec 17, 2020
    25
    无非轮询事件回调。
    fantastM
    fantastM
    Dec 17, 2020
    26
    先同步调用 a,再用线程池异步并行地调用 bcde 。

    因为整合数据时,需要保证 bcde 请求调用完成,所以就用一下 CountDownLatch 来实现这个等待机制。
    XDJI
    XDJI
    Dec 17, 2020
    27
    就是 20 21 解法 全链路异步
    kkkkkrua
    kkkkkrua
    Dec 17, 2020
    28
    这不就是考察 CompletableFuture ?
    surfire91
    surfire91
    Dec 17, 2020
    29
    @fantastM 为什么不先调用 acde,然后等 a 返回了再调 b
    WaldenHorizon
    WaldenHorizon
    Dec 17, 2020
    30
    a+b 一个 goroutine,cde 各一个 goroutine,主线程 waitgroup
    zy445566
    zy445566
    Dec 17, 2020
    31
    如果是 js 的话,这样就行
    ```js
    const data = await a();
    const dataList = await Promise.all([c(),d(),d()]);
    // 整合数据
    ```
    Jooooooooo
    Jooooooooo
    Dec 17, 2020
    32
    20l 答案差不多了
    liian2019
    liian2019
    Dec 17, 2020
    33
    public static void test() throws Exception{
    Map<String,String> resultMap = new HashMap<>();
    CompletableFuture.allOf(CompletableFuture.supplyAsync(() -> {
    // 调用 A
    String aResult = "Hello";
    resultMap.put("A",aResult);
    return aResult;
    }, executor).thenAcceptAsync(aResult -> {
    // 调用 B
    String bResult = aResult + " World";
    resultMap.put("B",bResult);
    }), CompletableFuture.runAsync(() -> {
    // 调用 C
    String cResult = "CValue";
    resultMap.put("C",cResult);
    },executor), CompletableFuture.runAsync(() -> {
    // 调用 D
    String dResult = "DValue";
    resultMap.put("D",dResult);
    },executor),
    CompletableFuture.runAsync(() -> {
    // 调用 E
    String eResult = "EValue";
    resultMap.put("E",eResult);
    },executor)).join();
    System.out.println(JSON.toJSONString(resultMap));
    }
    luvroot
    luvroot
    Dec 17, 2020❤️1
    34
    ab 打包成一个微服务,ecd 做成 3 个微服务,即可
    gengzi
    gengzi
    Dec 17, 2020
    35
    多线程异步( Callable ),异步调用 a,调用 cde,等待 a 返回结果,再调用 b 。 最终的时延 acde 服务最长的一个耗时+b 服务耗时。
    crclz
    crclz
    Dec 17, 2020
    36
    System.ReactiveX rxjs rxjava
    mxT52CRuqR6o5
    mxT52CRuqR6o5
    Dec 17, 2020
    37
    就是在满足调用条件时就马上去调用,把这个逻辑写出来就行
    Achieve7
    Achieve7
    Dec 17, 2020
    38
    CompletableFuture 或者 ForkJoinPool 都可以 如果是微服务 就异步呗
    IssacTomatoTan
    IssacTomatoTan
    Dec 17, 2020 via Android
    39
    Js:
    const f = new Promise(async (r)=>{
    await a();
    await b();
    r();
    })
    promise.all([c,d,e,f]).then
    laminux29
    laminux29
    Dec 18, 2020❤️1
    40
    微服务这功能,从本质上来说,首先是软件工程与管理上的问题,目的是为多人协同的大中型软件项目服务,是用增加组件间延时的代价来换取更快的平均运行性能与开发协作效率,所以时延高是必须,是代价,没办法从原理上降低。否则,如果低时延是刚需,那就不应该用微服务,而是单机 + 进程内部调用,这样子延时才会最小化。

    其他细节上的问题,楼上的老哥们已经说了。
    js8510
    js8510
    Dec 18, 2020
    41
    x->b and x->a pre call
    got b response, retrieve a response with the real ->a call
    这样 是 max(x->b, x->a pre call) + x-a round trip 的时间

    如果 a processing time 短于 b 还可以。
    x->b and x->a precall
    b processing and then retrieve ->a response
    response x

    这样的时间 和 x->a round trip + a prossing time 是一样的
    mitsuizzz
    mitsuizzz
    Dec 18, 2020
    42
    20L 是我常用的方法,之前做过清理各个服务的数据,整合各个服务备份的脚本
    519718366
    519718366
    Dec 18, 2020 via Android
    43
    其实面试回答,cde 异步请求就完事了…
    在追问你怎么异步实现,当然优先微服务框架特性,再语言特性实现
    Suddoo
    Suddoo
    Dec 23, 2020
    44
    @luvroot 感觉你这个最简洁明了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4223 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 134ms · UTC 05:39 · PVG 13:39 · LAX 21:39 · JFK 00:39
    ♥ Do have faith in what you're doing.