Jetty HttpClient 如何使用线程?

问题描述 投票:0回答:1

Jetty

HttpClient
在启动时启动线程,并且似乎生成了相当数量的线程。我对此感到有点惊讶,因为我认为基于
nio
的网络的优点之一是通过线程复用对话。使用
HttpClient.setExecutor(...)
控制线程数很容易,但我不确定如何考虑应该需要多少个线程。该库是否需要每个并发 HTTP 请求一个线程,如
HttpURLConnection
可能那样?它在某种程度上是复用的吗?

我正在定义一个将在我的应用程序中长期存在的 API 客户端,并尝试在保持较小的占用空间与实现良好的并发性能之间取得平衡。

非常感谢您的见解。

java multithreading jetty
1个回答
7
投票

Jetty 的

HttpClient
线程池默认是 Jetty 的
QueuedThreadPool
,因此它确实启动了一些线程。

这些线程用于执行 DNS 查找(在 Java 中是阻塞的,并且不可能使其成为非阻塞)并接收响应。 请求可以由应用程序线程和池线程发送(后者在请求已排队的情况下)。

Jetty 的

HttpClient
是完全非阻塞的,因为它基于 Jetty NIO 库,而 Jetty NIO 库又基于 JDK 的 NIO 库。 因此,它不需要每个请求一个线程,并且它能够在几个线程中复用许多请求/响应。

即使

HttpClient
在执行网络 I/O 时是完全非阻塞的,但有些事情(例如超时和 DNS)确实需要额外的线程,这就是您看到额外线程的原因。

如果您需要平衡小占用空间和良好的并发性,您一定要尝试通过调整传递给

HttpClient
的执行器来找到最佳位置。

另一个需要调整的重要因素是选择器的数量,在

HttpClientTransportOverHTTP
级别配置,请参阅 https://eclipse.dev/jetty/documentation/jetty-12/programming-guide/index.html#pg-client- http-传输.

对于什么是正确的线程数没有通用的答案,因为它取决于许多因素。正如我所说,你必须尝试一下并调整各种参数。

例如,如果目标地址都是众所周知的(例如内部网络),您可以将默认的异步

SocketAddressResolver
替换为:

httpClient.setSocketAddressResolver(new SocketAddressResolver.Sync());

这将消除执行 DNS 查找的额外调度。

对于通常低于 1-5 千的套接字数量,选择器的数量可以保持为 1,具体取决于硬件。

HttpClient
可用的线程数越少,负载增加时的延迟就越长。
QueuedThreadPool
能够根据需要生成新线程,并在不再需要它们时终止它们,表现得弹性(因此通常保留默认配置),但您可以根据您的情况尝试不同的配置。

© www.soinside.com 2019 - 2024. All rights reserved.