代码之家  ›  专栏  ›  技术社区  ›  Maxim Terletsky

OkHttpClient-最佳ThreadPoolTaskExecutor

  •  1
  • Maxim Terletsky  · 技术社区  · 9 年前

    试图理解我在传输到OkHttpClient时可以定义的最佳Java ThreadPoolTaskExecutor,延迟方面。目前,我们的定义如下:

    <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,最小线程数是 最大值(32,numCpu)*2 最大线程数为 最大值(32,numCpu)*8 .在我们的情况下 可以在16到24之间变化(如果考虑了超线程,则将该数字乘以2,对吗?)。 但当你仔细考虑时-我不确定这里的线程数量是否应该与CPU计数有某种联系。这些是HTTP客户端的发送/接收线程,而不是业务逻辑线程。所以也许CPU计数不应该是这里的偶数因素。

    有什么意见/建议吗?

    1 回复  |  直到 9 年前
        1
  •  1
  •   CodeBlind    9 年前

    在我看来,您的线程池似乎被用来同时进行大量HTTP连接,这意味着您的性能受到I/O(以及潜在的内存)的限制,而不是CPU使用的限制。线程的“最佳”数量将受到许多其他因素的限制。。。

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

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

    2.每个线程的内存使用率是非零的,即使它们不做任何密集型工作。

    分配给Java的默认堆栈空间量因供应商而异,但大约为1MB。这听起来不太多,但如果您需要运行数千个线程来保持一次活动的客户端连接,那么您将需要单独为堆栈空间分配千兆字节的RAM。可以使用 -Xss[size] VM参数,但这对于VM是全局的,因此收缩堆栈大小可能会导致程序的其他区域出现问题,这取决于您正在做什么。

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

    最后

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