我有两个端点:/parent
和/child/{parentId}
两者都将返回List
让我们假设每次通话将花费两秒钟。
因此,如果我打电话给/parent
并在列表中有10个父母,并且我想打电话给每个孩子并填充每个孩子,那么我总共需要22秒(/parent
只需2秒,是/child/{parentId}
的10倍每次2秒)
在Spring和Java 10中,我可以结合使用RestTemplate
和Future
进行异步调用。
在此代码段中,/slow-five
是对父级的调用,而/slow-six
是对子级的调用。
public List<Child> runSlow2() {
ExecutorService executor = Executors.newFixedThreadPool(5);
long start = System.currentTimeMillis();
RestTemplate restTemplate = new RestTemplate();
var futures = new ArrayList<Future<List<Child>>>();
var result = new ArrayList<Child>();
System.out.println("Start took (ms) : " + (System.currentTimeMillis() - start));
var responseFive = restTemplate.exchange("http://localhost:8005/api/r/slow-five", HttpMethod.GET, null,
new ParameterizedTypeReference<ResponseWrapper<Parent>>() {
});
for (var five : responseFive.getBody().getData()) {
// prepare future
var future = executor.submit(new Callable<List<Child>>() {
@Override
public List<Child> call() throws Exception {
var endpointChild = "http://localhost:8005/api/r/slow-six/" + five.getId();
var responseSix = restTemplate.exchange(endpointChild, HttpMethod.GET, null,
new ParameterizedTypeReference<ResponseWrapper<Child>>() {
});
return responseSix.getBody().getData();
}
});
futures.add(future);
}
for (var f : futures) {
try {
result.addAll(f.get());
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Before return took (ms) : " + (System.currentTimeMillis() - start));
return result;
}
忽略ResponseWrapper。就是这样的包装类
public class ResponseWrapper<T> {
private List<T> data;
private String next;
}
该代码运行正常,花了大约3-4秒的时间才能收集10个父母的所有孩子。但是我觉得效率不高。
此外,Spring 5具有WebClient
应该可以执行此类操作的功能。
但是,我找不到这种分层调用的任何示例。 WebClient
上的大多数示例仅涉及对单个端点的简单调用,而没有依赖性。
有什么线索可以使用WebClient实现相同的目的吗?异步调用多个/child
并合并结果?
谢谢
答案 0 :(得分:0)
从10个父母那里收集所有孩子大约需要3-4秒。
我认为我们应该弄清楚是什么放慢了方法runSlow2()的速度。
您的方法多次调用端点。通过执行调用并行性并从中收集结果,可以提高性能。
我不认为restTemplate太慢,您的代码没什么问题,也许您的端点也很慢。
一种改进是可以代替对/ child / {parentId}进行并行调用,而可以引入一个新的终结点,该终结点可以接受parentId的列表。
希望对您有所帮助。