【问题标题】:How to execute non blocking HTTP calls in Java?如何在 Java 中执行非阻塞 HTTP 调用?
【发布时间】:2020-07-02 21:48:17
【问题描述】:

我有一个第三方 API,我使用 HTTP GET 请求调用它。每个请求都需要几秒钟才能得到响应。

目前我正在使用一个 CompletableFuture,它在大小为 64 的 FixedThreadPool 上执行。这会导致线程被阻塞,直到它收到对 GET 请求的响应,即线程在发送 GET 响应后处于空闲状态,直到它们收到回复。因此,我可以发送的最大同时请求数受到线程大小的限制,即此处为 64。

我可以使用什么来代替 CompletableFuture,这样我的线程就不会闲置等待响应?

【问题讨论】:

  • 所以增加线程池,或者无限使用。但是你真的有 64 个待处理的 GET 请求同时待处理吗?
  • 我实际上可以同时处理数千个 GET 请求。除了使用这种大小的线程池之外,还有其他方法吗?线程只需发送 GET 请求并收集响应。
  • 几千个空闲线程没什么问题,非阻塞HTTP严重难以实现。
  • 拥有多个线程的问题是我们可能需要在扩展时保持线程池的大小不断变化。而且我们可以在 Java VM 上拥有的线程大小也不是那么大(根据这个答案是 6500)。 stackoverflow.com/questions/763579/…
  • 所以设置得更低。无论如何,您实际上不能同时执行数千个 GET 请求。网络不是多线程的。但是你引用的问题是八岁的问题。你需要做一些实验。

标签: java completable-future


【解决方案1】:

正如@user207421 所说:

  • 真正的异步(即事件驱动)HTTP 客户端应用程序很复杂。
  • 多线程(但基本上是同步的)HTTP 客户端应用程序更简单,并且可以扩展到尽可能多的线程。
  • 假设您有 64 个工作线程处理请求,实际瓶颈很可能是您的物理网络带宽或您可用的客户端 CPU。如果你已经达到了这些限制,那么:

    • 增加工作线程的数量并没有帮助,并且
    • 切换到异步(事件驱动)模型无济于事。
  • 第三种可能性是瓶颈是服务器端资源限制或速率限制。在这种情况下,增加客户端线程数可能会有所帮助、没有效果,或者会使问题变得更糟。这将取决于服务器的实现方式、请求的性质等。

如果您的瓶颈确实是线程数,那么尝试一个简单的方法是减少工作线程堆栈大小,以便您可以运行更多线程。默认堆栈大小通常为 1MB,这可能远远超过它需要的大小。 (如果这是一个真正的问题,这也将减少 ... erm ... 空闲线程的内存开销。)

周围有一些 Java 异步 HTTP 客户端库。但我从来没有用过,也不能推荐一个。和@user207421 一样,我不相信改变的努力会真正得到回报。


我可以[做什么] 使我的线程不会闲置等待响应?

空闲线程实际上不是问题。空闲线程仅使用内存(以及一些可能在这里可能无关紧要的次要影响)。除非你内存不足,否则影响不大。

注意:如果您的客户端在线程等待服务器响应时还有其他事情要做,操作系统线程调度程序将切换到不同的线程。

所以我可以同时发送的最大请求数受到我的线程 [pool] 大小的限制,即此处为 64。

确实如此。但是,发送更多同时请求可能无济于事。如果客户端线程处于空闲状态,那可能意味着瓶颈要么是网络,要么是服务器端的某事。如果是这种情况,添加更多线程不会增加吞吐量。相反,单个请求将(平均)花费更长的时间,并且吞吐量将保持不变......或者如果服务器开始从其请求队列中丢弃请求,则可能会下降。

最后,如果您担心大量工作线程闲置(等待下一个任务执行)的开销,请使用可以收缩和扩大其线程池以满足不断变化的工作负载的执行服务或连接池.

【讨论】:

    猜你喜欢
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多