У меня есть две конечные точки: /parent
и /child/{parentId}
Обе вернут список
Предположим, что каждый вызов займет две секунды.Поэтому, если я позвоню /parent
и у меня будет 10 родителей в списке, и я хочу позвонить и заполнить каждого ребенка, мне понадобится всего 22 секунды (2 секунды для /parent
, 10 раз /child/{parentId}
с 2 секундами для каждого)
В Spring и Java 10 я могу использовать RestTemplate
в сочетании с Future
для выполнения асинхронного вызова.
В этом фрагменте /slow-five
- это вызов родителя, а /slow-six
- вызовchild.
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;
}
Код работает нормально, для сбора всех детей от 10 родителей потребовалось около 3-4 секунд.Но я не думаю, что это эффективно.
Более того, у Spring 5 есть WebClient
, который должен уметь делать подобные вещи.
Однако я не могу найти ни одного примера для такого рода иерархических вызовов.Большинство примеров на WebClient
включает в себя только простой вызов одной конечной точки без зависимости.
Любая подсказка, как я могу использовать WebClient для достижения тех же целей?Вызовите несколько /child
асинхронно и объедините результат?
Спасибо