【发布时间】:2017-04-30 16:36:43
【问题描述】:
我创建了一个 Spring Boot (1.4.2) REST 应用程序。 @RestController 方法之一需要调用第 3 方 API REST 操作 (RestOp1),该操作返回 100-250 条记录。对于 RestOp1 返回的每条记录,在同一方法中,必须调用同一 3rd 方 API (RestOp2) 的另一个 REST 操作。我的第一次尝试涉及使用基于大小为 100 的固定线程池的 Controller 类级别 ExecutorService,以及返回与 RestOp2 响应对应的记录的 Callable:
// Executor thread pool - declared and initialized at class level
ExecutorService executor = Executors.newFixedThreadPool(100);
// Get records from RestOp1
ResponseEntity<RestOp1ResObj[]> restOp1ResObjList
= this.restTemplate.exchange(url1, HttpMethod.GET, httpEntity, RestOp1ResObj[].class);
RestOp1ResObj[] records = restOp1ResObjList.getBody();
// Instantiate a list of futures (to call RestOp2 for each record)
List<Future<RestOp2ResObj>> futureList = new ArrayList<>();
// Iterate through the array of records and call RestOp2 in a concurrent manner, using Callables.
for (int count=0; count<records.length; count++) {
Future<RestOp2ResObj> future = this.executorService.submit(new Callable<RestOp2ResObj>() {
@Override
public RestOp2ResObj call() throws Exception {
return this.restTemplate.exchange(url2, HttpMethod.GET, httpEntity, RestOp2Obj.class);
}
};
futureList.add(future);
});
// Iterate list of futures and fetch response from RestOp2 for each
// record. Build a final response and send back to the client.
for (int count=0; count<futureList.size(); count++) {
RestOp2ResObj response = futureList.get(count).get();
// use above response to build a final response for all the records.
}
上述代码的性能至少可以说是糟糕透了。 RestOp1 调用(仅调用一次)的响应时间约为 2.5 秒,而 RestOp2 调用(为每条记录调用)的响应时间约为 1.5 秒。但代码执行时间在 20-30 秒之间,而不是预期的 5-6 秒!我在这里遗漏了一些基本的东西吗?
【问题讨论】:
-
你能添加你的
executorService的初始化吗? -
@ilopezluna 我在代码 sn-p 的顶部添加了执行器服务的初始化。那是该类的成员,显然是在相关方法之外声明的。
-
好吧,我觉得还可以。您是否检查过您的任务是否已并行执行?例如记录线程名称,您可以在创建线程池时定义名称:nurkiewicz.com/2014/11/executorservice-10-tips-and-tricks.html
-
@ilopezluna 这是一组很棒的技巧。即使任务没有并行执行,我想知道什么是阻塞。我将尝试一些日志记录,希望能有所启发。有没有更好的方法/模式来做到这一点?
-
我不知道有什么模式可以实现,我建议你记录线程的名称(看看它们是否并行运行),每个任务的执行时间并计算平均值时间(只是为了确保 api 的响应时间是您所期望的),然后您将获得所有信息来查看谁一直在花费时间。也许只是一个查询,它花费的时间比您预期的要多。试试看并告诉我们。
标签: multithreading spring-boot resttemplate