![]() | 1 Yoock 2020-12-16 22:10:13 +08:00 waitgroup |
3 fanyiaa 2020-12-16 22:19:59 +08:00 via Android c#里用 task 很容易。java 不知道有什么简便方法 |
4 Cbdy 2020-12-16 22:21:39 +08:00 ![]() let resultA const [resultB, resultC, resultD, resultE] = await Promise.all([a().then(ra => { resultA = ra; return b() }), c(), d(), e()]) |
![]() | 5 Yoock 2020-12-16 22:23:33 +08:00 搜到一个 [CountDownLatch]( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html) 不太了解 Java,你看一下 |
![]() | 6 luxinfl OP 我想说的不是 AQS 方面的东西。是侧重于 java 微服务相关的 |
![]() | 7 pkwenda 2020-12-16 22:45:45 +08:00 比如 zuul 网关应该可以写 groovy 从注册中心获取微服务,先调用啊,并发调用 cde,代码整合 kong 这种可以写 lua 插件 是这个意思吧,不进行并发处理延时是一样的 网关做 merge |
![]() | 8 mango88 2020-12-16 23:49:08 +08:00 可以用几个 future,然后用 CompletableFuture.allOf() ,等所有 future 完成再去组装数据 |
9 xizismile 2020-12-16 23:51:10 +08:00 via Android 去看看 CompletableFuture 类 |
![]() | 10 hangszhang 2020-12-16 23:59:11 +08:00 Java 的话, CompleteFuture 或者 RxJava 或者 Future |
![]() | 11 DoctorCat 2020-12-17 01:57:50 +08:00 看起来是架构方案题,不是编程细节吧。b 调用 a,并降低时延,意味着 b 与 a 的调用链路最短+系统状态保持最优啊。如果分别部署在不同实例,那最好 b 与 a 同一个机架同一个子网,物理距离和网络逻辑位置最短的原则。 数据聚合最好设计一个数据聚合层比如引入 MQ 而且最好是 pubsub 机制……保持 tcp 长连接替代 HTTP 等等,还有 kernel 网络相关的调优、系统进程 CPU 亲和性的调优等等。 |
![]() | 12 beidounanxizi 2020-12-17 02:33:21 +08:00 @luxinfl go 的 waitgroup Java 的 countdownlatch 都可以实现 , |
13 carlclone 2020-12-17 06:52:39 +08:00 via Android 这题难道不是考察分布式事务吗,楼上的都在讲什么乱七八糟的 |
14 noogler67 2020-12-17 08:44:47 +08:00 via iPhone 时延的话,就是同时发起 acde,等完成后再发起 b |
![]() | 15 anthow 2020-12-17 08:55:52 +08:00 整几个 CompletableFuture |
16 Peachl 2020-12-17 09:00:55 +08:00 ![]() @carlclone 分布式事务是保证事务的 明显这个位置问的是如何做到顺序性的 completableFuture 就是正解 |
![]() | 17 blessyou 2020-12-17 09:18:49 +08:00 js 的话大概是 Promise.all() |
19 liuhuan475 2020-12-17 09:41:56 +08:00 Future |
20 sonice 2020-12-17 09:55:47 +08:00 ![]() ``` 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); ``` |
21 Cbdy 2020-12-17 10:35:42 +08:00 我是 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()); |
22 gmywq0392 2020-12-17 10:37:30 +08:00 回调 |
23 dddz97 2020-12-17 10:40:13 +08:00 感觉想问的点是 MQ 之类的 |
![]() | 24 shyrock 2020-12-17 10:54:30 +08:00 插眼等有效回答。 |
![]() | 25 qiaobeier 2020-12-17 10:58:19 +08:00 无非轮询事件回调。 |
![]() | 26 fantastM 2020-12-17 11:39:18 +08:00 先同步调用 a,再用线程池异步并行地调用 bcde 。 因为整合数据时,需要保证 bcde 请求调用完成,所以就用一下 CountDownLatch 来实现这个等待机制。 |
27 XDJI 2020-12-17 14:36:03 +08:00 就是 20 21 解法 全链路异步 |
![]() | 28 kkkkkrua 2020-12-17 14:40:27 +08:00 这不就是考察 CompletableFuture ? |
![]() | 30 wangritian 2020-12-17 17:31:01 +08:00 a+b 一个 goroutine,cde 各一个 goroutine,主线程 waitgroup |
![]() | 31 zy445566 2020-12-17 17:41:49 +08:00 如果是 js 的话,这样就行 ```js const data = await a(); const dataList = await Promise.all([c(),d(),d()]); // 整合数据 ``` |
32 Jooooooooo 2020-12-17 18:46:30 +08:00 20l 答案差不多了 |
33 liian2019 2020-12-17 19:01:54 +08:00 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)); } |
34 luvroot 2020-12-17 19:14:30 +08:00 ![]() ab 打包成一个微服务,ecd 做成 3 个微服务,即可 |
35 gengzi/a> 2020-12-17 19:24:22 +08:00 多线程异步( Callable ),异步调用 a,调用 cde,等待 a 返回结果,再调用 b 。 最终的时延 acde 服务最长的一个耗时+b 服务耗时。 |
36 crclz 2020-12-17 19:30:22 +08:00 System.ReactiveX rxjs rxjava |
37 mxT52CRuqR6o5 2020-12-17 19:30:37 +08:00 就是在满足调用条件时就马上去调用,把这个逻辑写出来就行 |
![]() | 38 Achieve7 2020-12-17 19:30:50 +08:00 CompletableFuture 或者 ForkJoinPool 都可以 如果是微服务 就异步呗 |
39 IssacTomatoTan 2020-12-17 19:42:57 +08:00 via Android Js: const f = new Promise(async (r)=>{ await a(); await b(); r(); }) promise.all([c,d,e,f]).then |
40 laminux29 2020-12-18 00:57:43 +08:00 ![]() 微服务这功能,从本质上来说,首先是软件工程与管理上的问题,目的是为多人协同的大中型软件项目服务,是用增加组件间延时的代价来换取更快的平均运行性能与开发协作效率,所以时延高是必须,是代价,没办法从原理上降低。否则,如果低时延是刚需,那就不应该用微服务,而是单机 + 进程内部调用,这样子延时才会最小化。 其他细节上的问题,楼上的老哥们已经说了。 |
41 js8510 2020-12-18 08:45:14 +08:00 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 是一样的 |
![]() | 42 mitsuizzz 2020-12-18 11:57:15 +08:00 20L 是我常用的方法,之前做过清理各个服务的数据,整合各个服务备份的脚本 |
![]() | 43 519718366 2020-12-18 12:01:06 +08:00 via Android 其实面试回答,cde 异步请求就完事了… 在追问你怎么异步实现,当然优先微服务框架特性,再语言特性实现 |