Jetty HttpClient如何使用Threads?

Ste*_*man 3 java multithreading jetty

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

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

非常感谢任何见解.

sbo*_*det 5

HttpClient默认情况下,Jetty的线程池是Jetty的QueuedThreadPool,因此它确实启动了几个线程.

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

Jetty HttpClient是完全无阻塞的,因为它基于Jetty NIO库,而后者又基于JDK的NIO库.因此它并不需要每个请求的线程,它能够在几个线程复多次请求/响应.

即使HttpClient在执行网络I/O时完全没有阻塞,也有一些事情,例如超时和DNS需要额外的线程,这就是你看到其他线程的原因.

如果您需要平衡小占用空间和良好的并发性,那么您必须通过调整传递给它的执行程序来尝试并找到最佳位置HttpClient.

要调整的另一个重要因素是在该HttpClientTransportOverHTTP级别配置的选择器数量,请参阅http://www.eclipse.org/jetty/documentation/current/http-client-transport.html#_http_1_1_transport.

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

例如,如果目标地址都是众所周知的(例如内部网络),则可以使用以下命令替换默认异步SocketAddressResolver:

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

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

对于许多通常低于1-5千的插座,选择器的数量可以保持为1,具体取决于硬件.

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