【问题标题】:Java pooling connection optimizationJava 池连接优化
【发布时间】:2013-12-08 18:11:33
【问题描述】:

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

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

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

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

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

谢谢!

【问题讨论】:

    标签: java multithreading apache http


    【解决方案1】:

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

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

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

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

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

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

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


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

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

    【讨论】:

      猜你喜欢
      • 2013-04-08
      • 2017-03-13
      • 1970-01-01
      • 2016-07-08
      • 2012-05-18
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      相关资源
      最近更新 更多