2013-11-23 91 views
1

哪些公共指导方针/建议可以在Java中配置http连接池以支持到同一服务器的大量并发http调用?我的意思是:Java池连接优化

  • 最大总连接
  • 每路最大默认连接
  • 重用策略
  • 永葆战略
  • 存活时间
  • 连接超时
  • ....

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

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

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

谢谢!

回答

2

线程的数量/该是最适合你的实现连接取决于执行(你没有张贴),但这里有按要求的一些准则:

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

  • 如果你的线程很少被阻塞,那么内核* 2是一个很好的基准测试开始。

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

现在最优化的情况下,显然是第一位的,但要获得这一个,你需要删除从您的代码堵不如尽你所能。如果你在非阻塞模式下使用NIO包(这不是Apache包的做法),Java可以为IO操作执行此操作。

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

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


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

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