如何在 Java 中执行非阻塞 HTTP 调用?

Aay*_*edi 8 java completable-future

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

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

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

Ste*_*n C 8

正如@user207421 所说:

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

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

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

有一些 Java 异步 HTTP 客户端库。但我从未使用过,也无法推荐之一。和@user207421一样,我不相信改变的努力会真正得到回报。


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

空闲线程实际上不是问题。空闲线程仅使用内存(以及一些可能的次要影响,这些影响在这里可能并不重要)。除非你记忆力差,否则没什么区别。

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

因此,我可以发送的最大并发请求数受到线程[池]大小的限制,即此处的 64。

那是真实的。但是,同时发送更多请求可能不会有帮助。如果客户端线程闲置,这可能意味着瓶颈要么是网络,要么是服务器端的某些东西。如果是这种情况,添加更多线程不会增加吞吐量。相反,单个请求将花费(平均)更长的时间,并且吞吐量将保持不变……或者如果服务器开始从其请求队列中删除请求,则吞吐量可能会下降。

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