You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Reactive如何并行调用多服务实现性能优化

问题根源

你当前的代码性能差完全是错误使用WebClient导致的:

  • 两次调用.block()把原本异步非阻塞的请求强行改成了同步阻塞,会直接占住工作线程等下游响应,高并发下线程很快就会被打满
  • 两个下游请求是串行执行的,必须等第一个联系人接口返回完才会发第二个车辆接口的请求,总耗时是两个接口耗时加和,IO等待的时间完全被浪费了。
改造方案

Spring Reactive栈的核心规则是:非阻塞链路中绝对不要随意调用.block()方法,接口返回值需要使用响应式类型Mono/Flux。对于没有依赖关系的多个下游请求,使用Mono.zip实现并行调用,总耗时等于两个下游接口中耗时更长的那个,性能提升非常明显。

改造后的完整代码如下:

@RestController
public class CustomerController {

    @Autowired
    private WebClient wc;

    @GetMapping("/servicestatus")
    public Mono<String> getStatus() {
        return Mono.just("up");
    }

    @RequestMapping(value="/customer/{cid}", method=RequestMethod.GET)
    public Mono<CustomerDetails> getCustomer(@PathVariable String cid) {
        // 声明两个下游请求逻辑,此时不会阻塞,也不会发起实际调用
        Mono<ContactDetails> contactMono = wc.get()
                .uri("http://localhost:8091/customer/" + cid + "/contactdetails")
                .retrieve()
                .bodyToMono(ContactDetails.class);

        Mono<VehicleDetails> vehicleMono = wc.get()
                .uri("http://localhost:8092/customer/" + cid + "/vehicledetails")
                .retrieve()
                .bodyToMono(VehicleDetails.class);

        // 并行执行两个请求,等所有结果返回后组装最终返回值
        return Mono.zip(contactMono, vehicleMono)
                .map(resultTuple -> {
                    ContactDetails svc1 = resultTuple.getT1();
                    VehicleDetails svc2 = resultTuple.getT2();
                    CustomerDetails customer = new CustomerDetails();
                    customer.setContactId(cid);
                    customer.setContactName(svc1.getContactName());
                    customer.setPostalCode(svc1.getPostalCode());
                    customer.setLicensePlate(svc2.getLicensePlate());
                    customer.setCarType(svc2.getCarType());
                    return customer;
                });
    }
}
关键注意事项
  • 传入Mono.zip的多个Mono会被框架自动并行订阅,不需要手动写线程池提交任务,WebClient本身基于Netty非阻塞IO模型,用少量事件循环线程就能支撑极高并发
  • 不要在Controller方法、响应式操作符(map/flatMap等)的lambda逻辑里调用.block(),这会直接破坏非阻塞链路,严重时会导致服务线程池耗尽
  • 确保项目引入的是spring-boot-starter-webflux依赖,而不是传统的spring-boot-starter-web依赖,否则无法正常运行响应式链路。

内容的提问来源于stack exchange,提问作者PAA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 20:27:21