Java池连接优化

标签 java multithreading apache http

在 Java 中配置 http 连接池以支持对同一服务器的大量并发 http 调用的通用指南/建议是什么?我的意思是:

  • 最大总连接数
  • 每条路线的最大默认连接数
  • 重用策略
  • 保持活力策略
  • 存活时间
  • 连接超时
  • ....

(我使用的是 Apache http components 4.3,但我可以探索新的解决方案)

为了更清楚,这是我的情况:

我开发了一个 REST 资源,它需要对 AWS CloudSearch 执行大约 10 次 http 调用,以便获得要在最终结果中收集的搜索结果(我确实无法通过单个查询获得)。 整个操作必须少于 0.25 秒。因此,我在 10 个不同的线程中并行运行 http 调用。 在基准测试期间,我注意到并发请求很少,只有 5 个,我的目标就达到了。但是,将并发请求增加到 30,由于大约需要 1 秒的连接时间,性能会大幅下降。在并发请求很少的情况下,连接时间约为 150 毫秒(更准确地说,第一个连接需要 1 秒,之后的所有连接大约需要 150 毫秒)。我可以确保 CloudSearch 在不到 15 毫秒的时间内返回其响应,因此我的连接池中某处存在问题。

谢谢!

最佳答案

最适合您的实现的线程/连接数量取决于该实现(您没有发布),但这里有一些要求的指南:

  • 如果这些线程根本不会阻塞,那么您应该拥有与内核一样多的线程(Runtime.availableCores(),这将包括超线程内核)。仅仅是因为 CPU 使用率不可能超过 100%。

  • 如果您的线程很少阻塞,cores * 2 是基准测试的良好开端。

  • 如果您的线程经常阻塞,您绝对需要使用各种设置对您的应用程序进行基准测试,以找到适合您的实现、操作系统和硬件的最佳解决方案。

现在最好的情况显然是第一个,但是要达到这个,您需要尽可能多地从代码中删除阻塞。如果您在非阻塞模式下使用 NIO 程序包(这不是 Apache 程序包的工作方式),Java 可以为 IO 操作执行此操作。

然后您有 1 个线程等待选择器并在任何数据准备好发送或读取时立即唤醒。然后该线程仅将数据从其源复制到目标并返回到选择器。在读取(传入数据)的情况下,此目标是阻塞队列,核心 数量的线程在其上等待。然后,其中一个线程将提取接收到的数据并进行处理,现在没有任何阻塞。

然后您可以使用阻塞队列的长度来调整对于您的任务和硬件而言合理的并行请求数。


第一次连接需要 >1 秒,因为它实际上必须通过 DNS 查找地址。所有其他连接暂时搁置,因为这样做两次没有意义。您可以通过调用 IP(如果您与负载均衡器交谈可能不太好)或通过使用初始请求“预热”连接来规避这种情况。之后的任何新连接都将使用缓存的 DNS 结果,但仍需要执行其他初始化,因此尽可能多地重用连接将大大减少延迟。使用 NIO,这是一项非常简单的任务。

此外还有HTTP-multi-requests ,即:您建立一个连接,但在一个请求中请求多个 URL,并在“同一行”上获得多个响应。这大大减少了连接开销,但需要服务器支持。

关于Java池连接优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20168997/

相关文章:

android - 为什么创建 C++11 线程会导致致命信号?

django - readthedocs 自托管 AttributeError : 'Settings' object has no attribute 'REDIS'

java - 调度模式下的多个微服务

java - Spring mvc + Security Pdf 显示空白

c++ - 可移植线程 API

apache - 无法使用 Chrome 访问网络

linux - Apache IP 地址有效,但 localhost 无效

Java 获取设置一类轮

java - 如何检查值是否是手动设置的,而不是使用 setValue(JSlider、JSpinner)设置的?

Python线程: Multiline Progress Report