与少数线程同时发送大量的HTTP请求
我们需要在我们的Java代码中连续一段时间同时向服务器端点发送大量HTTP请求(每秒数百个请求)。服务器需要〜4-5秒来响应每个请求。
基础代码是使用Apache HTTPClient(Classic)提出这些请求。由于该客户端正在阻止,因此我必须使用大量线程(在executorService.newfixedThreadPool()
中)同时发送请求以实现目标:启动这些线程,每个线程基本上做类似的事情:
while (time_elapsed < 3600 seconds) {
sendHttpRequest(); // this takes ~4-5 seconds, during which the current thread is blocked due to the nature of Apache
}
有两个问题:
- 当服务器在4-5秒内响应每个HTTP调用时,从理论上讲,我们需要400-500个线程以发送〜100个请求/秒,但是这大量线程将会消耗大量资源,并将导致许多上下文开关以及其他问题,因此实际上,他们不会真正发送到100个请求/秒,
- 因为每个线程必须等到当前的请求完成(4)(4 -5秒)在发送下一个之前,我们无法控制每秒发送的确切数量的请求。
如果我们可以灵活地切换到诸如 apache httpasyncclient 或 async-http-client t由于代码库的限制。
我的问题是,是否有另一种方法可以实现数百个并发请求/秒,使用少量线程,并且不使用异步HTTP客户端?完整的future是一种选择吗?
We have the need to send large amounts of HTTP requests to a server endpoint concurrently (hundreds of requests per second) continuously for some time, in our Java code. The server takes ~4-5 seconds to respond to each request.
The underlying code is making those requests using Apache HttpClient (classic). Since this client is blocking, I'm having to use large amounts of threads (in a ExecutorService.newFixedThreadPool()
) to send requests concurrently in order to achieve the goal: start these threads, where each thread basically does something like this:
while (time_elapsed < 3600 seconds) {
sendHttpRequest(); // this takes ~4-5 seconds, during which the current thread is blocked due to the nature of Apache
}
There are 2 problems:
- as the server responds to each HTTP call in 4-5 seconds, theoretically we will need 400-500 threads in order to send ~100 requests/second, but this huge amount of threads will consume lots of resources, and will leads to a lot of context switch as well as other problems, so in practice they won't really send as many as 100 requests/second
- as each thread has to wait until the current request to finish (4-5 seconds) before sending the next, we can't control the precise number of requests we send every second.
This would have been easy if we have the flexibility to switch to async http clients like Apache HttpAsyncClient or async-http-client, but unfortunately we can't due to the codebase's limitation.
My question is, is there another way to achieve hundreds of concurrent requests/second, with a small number of threads and without using an async HTTP client? Is CompletableFuture an option?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虚拟线程
virtual threads ( fibers )是 Java 21 。这是 project loom 。
在常规的Java并发中,Java中的线程与主机OS线程直接映射到一对一。问题在于,当代码在线程块中运行时,线程也会块。该线程暂停,直到执行代码未阻止为止。在等待呼叫i/o,网络I/O,数据库访问等时,线程可能会未使用,闲置,闲置。
相反,许多提出的虚拟线程映射到主机OS提供的每个“真实”线程。当代码由虚拟线程块执行时,虚拟线程被“停放”,放在一边,而另一个虚拟线程则位于主机OS线程上。当先前的虚拟线程的任务不再被阻止时,它将再次分配给主机OS线程以继续执行。
这个停车场和未标记非常有效。这意味着您可以同时拥有数千个甚至数百万的线程。
因此,您可以将数百个http请求设置为单个
运行
/callable
任务,然后将它们全部提交给适当的executor服务以立即执行。顺便说一句,Java现在包括a 新的http client 库。
Virtual threads
Virtual threads (fibers) is a new feature in Java 21. This is part of Project Loom.
In conventional Java concurrency, threads in Java are mapped directly one-to-one with host OS threads. The problem is that when code running in a thread blocks, the thread blocks too. That thread pauses until the executing code is unblocked. So much of the time a thread may go unused, sitting idle, while waiting for a call to storage I/O, network I/O, database access, etc. to return.
In contrast, many of the proposed virtual threads are mapped to each “real” thread provided by the host OS. When the code being executed by a virtual thread blocks, the virtual threads is “parked”, set aside, while another virtual thread takes its place on the host OS thread. When the prior virtual thread’s task is no longer blocked, it gets assigned again to a host OS thread for continued execution.
This parking and unparking is extremely efficient. This means you can have thousands, even millions, of simultaneous threads.
So you could set up your hundreds of HTTP requests as individual
Runnable
/Callable
tasks, and then submit them all to an appropriate executor service for immediate execution.By the way, Java now includes a new HTTP client library.