繁体   English   中英

在Spring REST中进行异步调用的有效方法

[英]Efficient way to do async call in Spring REST

我有两个端点: /parent/child/{parentId}都将返回List

假设每次通话将花费两秒钟。 因此,如果我打电话给/parent并在列表中有10个父母,并且我想打电话给每个孩子并填充每个孩子,则总共需要22秒( /parent为2秒, /child/{parentId}为10倍,每个为2秒)

在Spring和Java 10中,我可以结合使用RestTemplateFuture进行异步调用。
在此代码段中, /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并合并结果?

谢谢

从10个父母那里收集所有孩子大约需要3-4秒。


我认为我们应该弄清楚什么会使方法runSlow2()变慢。
您的方法对端点进行了多次调用。 通过执行调用并行性并从中收集结果,可以提高性能。
我认为restTemplate并不慢,您的代码也没什么问题,也许您的端点很慢。
一种改进是可以代替对/ child / {parentId}进行并行调用,而可以引入一个新的终结点,该终结点可以接受parentId的列表。 希望对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM