我正在使用带有超过1000个并发用户的spring boot应用程序的hikari cp。 我已经设置了最大池大小-
spring.datasource.hikari.maximum-pool-size=300
当我使用
查看mysql的进程列表时show processlist;
它显示最大300等于池的大小,从不超过最大池,这是故意的吗? 我认为池的大小意味着要维护连接,以便在将来需要对数据库的请求时可以重用这些连接,但是当需要时可以建立更多的连接。
另外,当我删除最大池配置时,我立即得到-
HikariPool-0-连接不可用,请求在30000ms后超时。
如何解决此问题。谢谢。
答案 0 :(得分:3)
是的,这是有意的。引用documentation:
此属性控制允许池达到的最大大小,包括空闲和正在使用的连接。基本上,此值将确定到数据库后端的最大实际连接数。合理的值最好由您的执行环境确定。当池达到此大小并且没有空闲连接可用时,对
getConnection()
的调用将在超时之前最多阻塞connectionTimeout
毫秒。请阅读about pool sizing。 默认值:10
因此,基本上,当所有300个连接都在使用中,而您尝试建立301 st 连接时,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秒才能完成,这很多。
尝试通过以下方式缩短执行时间: