【问题标题】:Does max connection pool also limits max connections to database?最大连接池是否也限制了与数据库的最大连接?
【发布时间】:2019-02-24 11:09:36
【问题描述】:

我正在将 hikari cp 与具有超过 1000 个并发用户的 spring boot 应用程序一起使用。 我已经设置了最大池大小-

spring.datasource.hikari.maximum-pool-size=300

当我使用 mysql 查看进程列表时

show processlist;

它显示最大 300 等于池大小。它永远不会超过最大池。这是故意的吗? 我认为池大小意味着保持连接,以便在以后需要对数据库的请求时可以重用连接,但在需要时可以建立更多连接。

此外,当我删除最大池配置时,我会立即得到-

HikariPool-0 - 连接不可用,请求在 30000 毫秒后超时。

如何解决此问题。提前致谢。

【问题讨论】:

    标签: database spring-boot hikaricp


    【解决方案1】:

    是的,这是有意的。引用documentation

    此属性控制池允许达到的最大大小,包括空闲和使用中的连接。基本上,此值将确定与数据库后端的实际连接的最大数量。一个合理的值最好由您的执行环境确定。当池达到这个大小并且没有空闲连接可用时,对getConnection() 的调用将在超时之前阻塞最多connectionTimeout 毫秒。请阅读about pool sizing默认值:10

    所以基本上,当所有 300 个连接都在使用中,并且您尝试建立 301st 连接时,Hikari 不会创建新连接(因为 maximumPoolSize 是绝对最大值) ,但它宁愿等待(默认为 30 秒),直到连接再次可用。

    这也解释了为什么会出现您提到的异常,因为默认值(未配置 maximumPoolSize 时)是 10 个连接,您可能会立即达到。

    要解决此问题,您必须找出这些连接被阻止超过 30 秒的原因。即使在有 1000 个并发用户的情况下,如果您的查询需要几毫秒或最多几秒钟,也应该没有问题。

    增加池大小

    如果您正在调用需要很长时间的非常复杂的查询,则有几种可能性。第一个是增加池大小。然而,这不推荐,因为计算最大池大小的推荐公式是:

    connections = ((core_count * 2) + effective_spindle_count)
    

    引用About Pool Sizing的文章:

    多年来在许多基准测试中都表现良好的公式是 为了获得最佳吞吐量,活动连接的数量应该在某个地方 靠近((core_count * 2) + effective_spindle_count)。核心数不应包括 HT 线程,即使启用了超线程。有效主轴计数为零,如果 活动数据集被完全缓存,并接近实际的主轴数 随着缓存命中率下降。 ......到目前为止还没有任何分析 该公式在 SSD 上的效果如何。

    如同一篇文章中所述,这意味着带有 1 个硬盘的 4 核服务器应该只有大约 10 个连接。即使您可能有更多的核心,我假设您没有足够的核心来保证您正在建立的 300 个连接,更不用说进一步增加它了。


    增加连接超时

    另一种可能性是增加连接超时。如前所述,当所有连接都在使用时,默认会等待 30 秒,也就是连接超时。

    您可以增加此值,以便应用程序在超时之前等待更长时间。如果您的复杂查询需要 20 秒,并且您的连接池包含 300 和 1000 个并发用户,那么理论上您应该将连接超时至少配置为 20 * 1000 / 300 = 67 seconds

    但请注意,这意味着您的应用程序可能需要很长时间才能向用户显示响应。如果您有 67 秒的连接超时,并且在完成复杂查询之前还有 20 秒,您的用户可能需要等待长达一分半钟。


    缩短执行时间

    如前所述,您的主要目标是找出您的查询需要这么长时间的原因。对于 300 个连接池、30 秒的连接超时和 1000 个并发用户,这意味着您的查询在完成之前至少需要 9 秒,这是很多。

    尝试通过以下方式改善执行时间:

    • 添加适当的索引。
    • 正确编写查询。
    • 改进数据库硬件(磁盘、内核、网络……)
    • 通过引入分页来限制您正在处理的记录数量,...。
    • 分工。看一下是否可以将查询拆分为较小的查询,从而产生中间结果,然后可以在另一个查询中使用,依此类推。只要您不在事务中工作,就会在两者之间释放连接,从而允许您以牺牲一些性能为代价来为多个用户提供服务。
    • 使用缓存
    • 预计算结果:如果您正在执行一些资源密集型计算,您可以尝试在应用程序不经常使用的时候预计算结果,例如。晚上,并将这些结果存储在可以轻松查询的不同表中。
    • ...

    【讨论】:

    • With a connection pool of 300, a connection timeout of 30 seconds and 1000 concurrent users, it means that your queries are taking at least 9 seconds before completing, which is a lot.你是怎么计算出来的?
    • @kamalhm 我用了timeout / (concurrent users / max pool),所以30/(1000/300)
    猜你喜欢
    • 1970-01-01
    • 2021-01-17
    • 2013-05-31
    • 2020-01-02
    • 2011-08-13
    • 2014-12-20
    • 2014-11-18
    • 2021-07-23
    • 1970-01-01
    相关资源
    最近更新 更多