如何在 Java 中执行非阻塞 HTTP 调用?
How to execute non blocking HTTP calls in Java?
我有第三方 API,我使用 HTTP GET 请求调用它。每个请求都需要几秒钟才能得到响应。
目前我正在使用 CompletableFuture,它在大小为 64 的 FixedThreadPool 上执行。这导致线程被阻塞,直到它收到 GET 请求的响应,即线程在发送 GET 响应后处于空闲状态直到他们收到回复。所以我可以发送的最大同时请求数受我线程大小的限制,即这里是 64。
我可以使用什么来代替 CompletableFuture,这样我的线程就不会闲置等待响应?
正如@user207421 所说:
- 真正异步(即事件驱动)的 HTTP 客户端应用程序很复杂。
- 多线程(但基本上是同步的)HTTP 客户端应用程序更简单,并且可以根据您的内存扩展到尽可能多的线程。
假设您有 64 个工作线程处理请求,实际瓶颈 可能 是您的物理网络带宽,或者您可用的客户端 CPU。如果您达到了这些限制,那么:
- 增加工作线程的数量没有帮助,
- 切换到异步(事件驱动)模型不会有帮助。
第三种可能是瓶颈是服务器端资源限制或速率限制。在这种情况下,增加客户端线程数可能会有所帮助,但没有效果,或者会使问题变得更糟。这将取决于服务器的实现方式、请求的性质等。
如果您的瓶颈确实是线程数量,那么可以尝试的一个简单方法是减少工作线程堆栈大小,以便您可以 运行 更多线程。默认堆栈大小通常为 1MB,这可能比需要的大得多。 (这也将减少……呃……空闲线程的内存开销,如果这是一个真正的问题。)
周围有一些 Java 异步 HTTP 客户端库。但我从未使用过,也无法推荐。和@user207421 一样,我不相信改变的努力会真正得到回报。
What can I [do] so that my threads don't sit idle waiting for the response?
空闲线程实际上不是问题。空闲线程仅使用内存(以及一些可能在这里无关紧要的次要影响)。除非你记性差,否则差别不大。
注意:如果在线程等待服务器响应时您的客户端有其他事情要做,OS 线程调度程序将切换到另一个线程。
So my maximum number of simultaneous requests I can send out is limited by my thread [pool] size i.e. 64 here.
没错。但是,同时发送更多请求可能无济于事。如果客户端线程处于空闲状态,那么 可能 意味着瓶颈要么是网络,要么是服务器端的 某些东西。如果是这种情况,添加更多线程不会增加吞吐量。相反,单个请求将花费(平均)更长的时间,并且吞吐量将保持不变......或者如果服务器开始从其请求队列中删除请求,则吞吐量可能会下降。
最后,如果您担心大量空闲工作线程池(等待下一个任务执行)的开销,请使用可以收缩和增长其线程池的执行服务或连接池来满足不断变化的工作量。
我有第三方 API,我使用 HTTP GET 请求调用它。每个请求都需要几秒钟才能得到响应。
目前我正在使用 CompletableFuture,它在大小为 64 的 FixedThreadPool 上执行。这导致线程被阻塞,直到它收到 GET 请求的响应,即线程在发送 GET 响应后处于空闲状态直到他们收到回复。所以我可以发送的最大同时请求数受我线程大小的限制,即这里是 64。
我可以使用什么来代替 CompletableFuture,这样我的线程就不会闲置等待响应?
正如@user207421 所说:
- 真正异步(即事件驱动)的 HTTP 客户端应用程序很复杂。
- 多线程(但基本上是同步的)HTTP 客户端应用程序更简单,并且可以根据您的内存扩展到尽可能多的线程。
假设您有 64 个工作线程处理请求,实际瓶颈 可能 是您的物理网络带宽,或者您可用的客户端 CPU。如果您达到了这些限制,那么:
- 增加工作线程的数量没有帮助,
- 切换到异步(事件驱动)模型不会有帮助。
第三种可能是瓶颈是服务器端资源限制或速率限制。在这种情况下,增加客户端线程数可能会有所帮助,但没有效果,或者会使问题变得更糟。这将取决于服务器的实现方式、请求的性质等。
如果您的瓶颈确实是线程数量,那么可以尝试的一个简单方法是减少工作线程堆栈大小,以便您可以 运行 更多线程。默认堆栈大小通常为 1MB,这可能比需要的大得多。 (这也将减少……呃……空闲线程的内存开销,如果这是一个真正的问题。)
周围有一些 Java 异步 HTTP 客户端库。但我从未使用过,也无法推荐。和@user207421 一样,我不相信改变的努力会真正得到回报。
What can I [do] so that my threads don't sit idle waiting for the response?
空闲线程实际上不是问题。空闲线程仅使用内存(以及一些可能在这里无关紧要的次要影响)。除非你记性差,否则差别不大。
注意:如果在线程等待服务器响应时您的客户端有其他事情要做,OS 线程调度程序将切换到另一个线程。
So my maximum number of simultaneous requests I can send out is limited by my thread [pool] size i.e. 64 here.
没错。但是,同时发送更多请求可能无济于事。如果客户端线程处于空闲状态,那么 可能 意味着瓶颈要么是网络,要么是服务器端的 某些东西。如果是这种情况,添加更多线程不会增加吞吐量。相反,单个请求将花费(平均)更长的时间,并且吞吐量将保持不变......或者如果服务器开始从其请求队列中删除请求,则吞吐量可能会下降。
最后,如果您担心大量空闲工作线程池(等待下一个任务执行)的开销,请使用可以收缩和增长其线程池的执行服务或连接池来满足不断变化的工作量。