如何使用RestTemplate实现REST接口并发调用 满足并行调用耗时1秒要求
实现REST接口并发调用的方案
已知配置参数
{ "url": "https://asia-east2-jsondoc.cloudfunctions.net/function-1?delay=1000", // 响应耗时为1000ms的接口地址 "isParallel": true, // 取值true为并行调用,false为串行调用 "count": "3" // 调用总次数 }
实现思路
RestTemplate本身是同步阻塞的HTTP客户端,单线程下发起多次调用会串行执行,3次调用总耗时会超过3秒。要实现并行调用总耗时接近1秒的需求,需要将每次调用提交到独立线程执行,同时等待所有线程执行完成即可。
代码实现(Spring环境)
1. 基础配置类
先注入RestTemplate和自定义线程池,避免频繁新建线程浪费资源:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Configuration public class RestConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } // 线程池核心线程数按最大并行调用数设置即可,这里适配3次并行调用的需求 @Bean public ExecutorService apiCallExecutor() { return Executors.newFixedThreadPool(3); } }
2. 业务调用逻辑
支持并行/串行模式切换,符合配置参数要求:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @Service public class ApiCallService { @Autowired private RestTemplate restTemplate; @Autowired private ExecutorService apiCallExecutor; public void callApi(String url, boolean isParallel, int count) throws Exception { long startTime = System.currentTimeMillis(); if (isParallel) { // 并行调用逻辑 List<CompletableFuture<String>> futureList = new ArrayList<>(); for (int i = 0; i < count; i++) { // 每次调用提交到线程池异步执行 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> restTemplate.getForObject(url, String.class), apiCallExecutor); futureList.add(future); } // 等待所有调用完成,设置超时时间避免异常阻塞 CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).get(2, TimeUnit.SECONDS); // 如需获取返回结果可遍历futureList调用get()方法 } else { // 串行调用逻辑 for (int i = 0; i < count; i++) { String result = restTemplate.getForObject(url, String.class); // 按需处理返回结果 } } System.out.println("总耗时:" + (System.currentTimeMillis() - startTime) + "ms"); } }
效果说明
当isParallel = true、count = 3时,3次请求会同时提交到线程池执行,每个请求耗时1000ms左右,总耗时会稳定在1000~1200ms区间,符合需求。
注意事项
- 线程池大小需要和最大并行调用数匹配,避免线程不足导致请求排队,增加总耗时
- 如果需要处理接口调用异常,可以在
supplyAsync的逻辑中添加try-catch,避免单个请求失败导致全量调用终止 - 生产环境建议用
ThreadPoolExecutor自定义线程池参数,不要直接用Executors的默认实现,方便控制队列长度、拒绝策略等
内容的提问来源于stack exchange,提问作者huk12353
相关产品推荐
相关产品推荐

