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
相关产品推荐
相关产品推荐

