为同时发起出站调用的请求设置 HTTP 连接池和线程执行器池是否有意义?

Does it make sense to have an HTTP connection pool and a thread executor pool for requests that originate the outbound calls at the same time?

我正在开发一项 RESTful 服务,该服务使用固定的执行程序池来处理出站调用请求,例如:

return CompletableFuture
    .supplyAsync(() -> {
      try {
        return restTemplate.exchange(uri, method, request, responseType, new Object[0]);
      } catch (IOException | URISyntaxException e) {
        e.printStackTrace();
      }
      return null;
    }, pool); //This is a thread pool executor with a fixed size
}

这个 restTemplate 还通过 PoolingHttpClientConnectionManager.

指定了一个固定的连接池(有很多样板我不会包括)

我将此解释为不必要地从原始线程卸载出站调用,这些线程被连接线程阻塞并且同时不执行任何其他任务。但是我无法说服作者坚持在涉及日志记录等辅助任务时提高性能(我认为应该是这里卸载的任务)

我在这里错过了什么?

孤立地看,它确实显得多余,但退一步说,它是有道理的。

主要原因是restTemplate.xx()是阻塞调用。如果使用它们,则必须等待 (http) 响应才能继续执行下一条指令。

解雇后忘记

现在假设这个 HTTP 调用是一个“即发即弃”调用,您只需发送数据,然后丢弃(或不需要)调用的响应来伪造您自己的响应。然后线程是提前发送响应的好方法。

独立工作

假设来电很重要,您需要它的响应,但同时您还有一些工作要做。也许您有一个要获取的数据库请求。也许是要读取的文件。可能需要进行另一个 HTTP 调用,或者几乎不需要 HTTP 调用响应的任何事情。 您可以在您的线程等待 HTTP 响应时开始处理它。 这是一个提升。

链接工作

假设你正在调用这个服务,而这个调用的结果,你必须进行另外两个调用,其中一个需要执行第三次调用,所有需要执行的结果第四个电话。

CompletableFutures(或其他响应式编程工具)就是为此而设计的。任何可以 运行 并发的东西,并且依赖性以隐藏它的声明方式设置。太棒了,而且性能极佳。

配置冲突

其余模板基于一些 HTTP 客户端,用于连接池。连接池有各种调整参数,例如每个主机或每个 HTTP 代理的出站总数 connections/sockets、套接字总数。

现在假设您要进行的 HTTP 调用由于某种原因受到速率限制(外部 API 技术或合同限制),并且 HTTP 池不知道或无法为此配置。那么使用线程池作为并发请求数的控制器可能是最简单的方法了。