OkHttpClient - 最佳 ThreadPoolTask​​Executor

OkHttpClient - Optimal ThreadPoolTaskExecutor

试图理解我在传输到 OkHttpClient 时可以定义的最好的 Java ThreadPoolTask​​Executor,延迟明智。目前我们的定义如下:

<property name="corePoolSize" value="#{ T(java.lang.Math).max(32,numCpu) * 2 }" />
<property name="maxPoolSize" value="#{ T(java.lang.Math).max(32,numCpu) * 8 }" />
<property name="queueCapacity" value="200"/>

即最大队列容量(新线程将在此处打开)为 200,最小线程数为 max(32,numCpu) * 2,最大线程数为 max(32,numCpu) * 8。在我们的例子中,numCpu 可能在 16 到 24 之间变化(尽管如果考虑超线程,则乘以该数字 *2,对吗?)。 但是当你考虑它时 - 我不确定这里的线程数是否应该以某种方式连接到 CPU 计数。这些是 HTTP 客户端的 sending/receiving 个线程,而不是 BusinessLogic 线程。所以也许 CPU 计数在这里不应该是偶数。

任何opinions/advice?

在我看来你的线程池被用来同时建立大量的 HTTP 连接,这意味着你的性能不是受到 CPU 使用的限制,而是受到 I/O 的限制(也可能是内存) . "optimal" 线程数量将受到许多其他因素的限制...

1. Link 客户端和端点之间的速度。

假设您的客户端连接到 1Gbps link,但在某个地方,您的所有端点只能以 1Mbps 的速度为您提供数据。为了最大化您的本地带宽,您需要同时 运行 1000 个连接才能充分利用您的 1Gbps link,这意味着您的线程池需要 运行 1000 个线程。但这也可能有问题,因为另一个问题...

2。每个线程的内存使用量不为零,即使它们没有执行任何密集操作。

分配给 Java 的默认堆栈量 space 因供应商而异,但大约为 1MB。这听起来不是很多,但如果您需要 运行 数千个线程来同时保持尽可能多的客户端连接处于活动状态,您将需要为堆栈分配 GB 的 RAM space独自的。您可以使用 -Xss[size] VM 参数调整每个线程分配的堆栈 space,但这对 VM 是全局的,因此缩小堆栈大小可能会导致程序的其他区域出现问题,具体取决于您正在做。

3。平均 HTTP 请求大小。

有时,它会归结为您希望每次 POST/GET 调用传输多少数据。回想一下,每个 TCP 连接都需要在发送任何数据之前进行初始握手。如果您希望在 HTTP 调用的生命周期内传输的数据量非常小,您可能无法同时保持数千个连接 运行ning,即使您有数千个线程可供使用。如果数量非常大,可能只需要几个并发连接就可以使您的客户端可用的总带宽达到最大。

终于...

如果您的所有端点 运行 都在网络上,您可能无法预测每个连接的 link 速度。我认为你能做的最好的事情就是对不同配置的性能进行基准测试,同时考虑这些因素中的每一个,并选择在你的典型操作环境中似乎能提供最佳性能的配置。它可能介于 N 和 1000 之间,其中 N 是您 运行 的内核数量,但将该数字确定为特定值将需要一些努力:)