【问题标题】: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?对于同时发起出站调用的请求,拥有一个 HTTP 连接池和一个线程执行器池是否有意义?
【发布时间】:2020-10-02 14:15:11
【问题描述】:

我正在开发一个 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 指定了一个固定的连接池(有很多样板文件我不会包括在内)。

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

我在这里错过了什么?

【问题讨论】:

    标签: java spring rest web-services


    【解决方案1】:

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

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

    一劳永逸

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

    独立工作

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

    连锁工作

    假设您正在调用这一项服务,并且根据这一次调用的结果,您必须进行另外两次调用,其中一次需要执行第三次调用,所有这些的结果都需要执行第四次打电话。

    CompletableFutures(或其他反应式编程工具)就是为此而设计的。任何可以同时运行的东西都可以,并且依赖项是以一种隐藏它的声明方式设置的。它很棒,而且性能也很好。

    配置冲突

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

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

    【讨论】:

    • 所有优点。对于我的具体示例,这些都不适用,但在可能的一系列服务中保持相同的模式是有好处的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 2019-11-07
    相关资源
    最近更新 更多