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