列表中每个 Id 的多个 RestTemplate 调用

Multiple RestTemplate calls for each Id in a List

我需要对 List<Ids> 中的每个 Id 进行多次 RestTemplate 调用。执行此操作的最佳方法是什么?

我用过parallelStream()。下面的代码片段是一个类似的场景。

List<Integers> employeeIds;
employeeIds.parallelStream().
.map(empId -> employeeService.fetchEmployeedetails(empId))
.collect(Collectos.toList());

employeeService.fetchEmployeedetails 是一种 restCall 它将获取所有 employeeDetails.

还有其他方法可以调优性能吗?

.parallelStream() 不保证多线程,因为它只会创建等于您拥有的内核数的线程。要真正强制多个线程同时执行此操作,您需要将 .parallelStream() 与 ForkJoinPool.

一起使用

使用 ForkJoinPool 的高性能

List<Employee> employees = new ArrayList();
ForkJoinPool forkJoinPool = new ForkJoinPool(50);
try {
    forkJoinPool.submit(() -> employeeIds.parallelStream().forEach(empId -> {
         Employee em = employeeService.fetchEmployeedetails(empId);
         synchronized(employees) {
              employees.add(em);
         }
    })).get();
} catch (Exception e) {
    e.printStackTrace();
    throw new BusinessRuleException(ErrorCodeEnum.E002501.value(), e.getMessage());
} finally {
    if (forkJoinPool != null) {
        forkJoinPool.shutdown(); // always remember to shutdown the pool
    }
}

这将确保 parallelStream() 最多创建 50 个线程,而不是取决于系统的内核数量。请确保您不要忘记在 finally 块中对池进行 shutdown()。也不要忘记触发线程执行的 .get();

ArrayList 的修改不是线程安全的,但 synchronized() 将提供这种安全性。由于添加到列表是非常小的操作,它也不会长时间占用线程。

使用这种方法,您将看到巨大的性能提升。

如何选择最佳线程数

太多线程会导致上下文切换并减慢进程。线程太少会使系统未得到充分利用。最佳线程数通常是您拥有的内核数的 10 倍左右。还取决于您要在线程中花费的时间。我通常会传递一个环境变量,这样我就可以在需要时调整数字 50。但是在我们拥有的四核实例上进行了大量实验后,我已经达到了 50。

    @Value("#{systemEnvironment['parallelism'] ?: 50}")
    protected int parallelism;

然后使用ForkJoinPool forkJoinPool = new ForkJoinPool(getParallelism());