一个首页接口要并行调用商品、库存、营销和推荐服务,你会怎么用 CompletableFuture 编排?
我的判断
首页聚合要并行的是相互独立的 I/O,核心做法是独立执行器、统一 deadline、局部降级和明确的结果组合。
商品、库存、营销和推荐之间没有依赖时可以并行,但我不会用默认 commonPool。这些都是阻塞 RPC,会放到专用有界线程池,并按下游分别限制并发。请求先算出总 deadline,各子调用拿剩余时间,不能每个都再等完整的两秒。
var product = supplyAsync(this::loadProduct, productPool);
var stock = supplyAsync(this::loadStock, stockPool);
var promo = supplyAsync(this::loadPromo, promoPool)
.completeOnTimeout(Promo.empty(), 120, MILLISECONDS);
商品和库存失败可能直接失败,推荐和营销可以返回空结果。组合时用 thenCombine 表达依赖,不在异步任务内部反复 join 把线程重新阻塞。接口结束或超时后取消还没必要执行的任务,并把 trace 上下文传进去。
压测会比较串行与并行后的 P95/P99、线程池队列、下游并发和超时率。并行能降低等待总时长,也会瞬间放大四倍下游流量,所以必须和限流一起设计。