在运行测试

时间:2017-11-06 16:11:06

标签: postgresql spring-boot datasource

我有一个Spring Boot应用程序,它为前端提供REST API。我正在使用jOOQ和Postgresql。我在本地执行所有集成测试时遇到此错误(大约1000次测试,这在执行700-800测试后开始发生):

org.postgresql.util.PSQLException: FATAL: sorry, too many clients already

我试图通过application.properties限制最大空闲和活动连接,但似乎这些值有些被忽略了。我只是在使用以下语句执行测试时监视打开的连接:

SELECT datname, state, query FROM pg_stat_activity;

这就是我的application.properties的样子:

spring.datasource.driverClassName = org.postgresql.Driver
spring.datasource.url = jdbc:postgresql://localhost:5432/xxx
spring.datasource.username = xxx
spring.datasource.password = xxx
spring.datasource.initialize = true
spring.datasource.continue-on-error = false
spring.jooq.sql-dialect = POSTGRES
spring.datasource.max-active = 50
spring.datasource.max-idle = 5

这就是我创建数据源的方式:

@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource() {
    return DataSourceBuilder
            .create()
            .build();
}

我看到jOOQ使用正确的数据源,连接由jOOQ正确处理(从数据源获取和释放连接)。所以问题不应该在jOOQ方面。

我的max_connections = 200中有postgresql.conf,所以我的Spring配置应该没问题。在运行测试时,我发现pg_stat_activity中的空闲连接比我在配置中指定的空闲连接多得多。最终,当测试由于PSQLException而开始失败时,我在pg_stat_activity中看到大约90-100个空闲连接。所以这产生了两个问题:

  1. 为什么我的测试会失败,尽管我的本地数据库应该允许比我在pg_stat_activity中看到的更多连接?
  2. 似乎忽略了application.properties中的数据源配置。知道为什么吗?

4 个答案:

答案 0 :(得分:3)

由于没有建议的答案,我正在发布我的解决方案。 简短版本:减小测试属性中的连接池大小:

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

长版本:Spring Boot 2默认使用HikariCP进行连接池,连接池大小的默认值为10(截至2019年1月)。在运行大量IT时,将多次创建Spring上下文,这意味着每个上下文从数据库获取10个连接。据我观察,测试分配连接的速度比释放它们的速度快。因此,在某个时候达到了数据库服务器允许的max_connections限制(默认情况下通常为100),这会导致“客户端过多”错误。

通过在测试属性中将连接池大小限制为2,我得以解决该问题。

答案 1 :(得分:2)

您应该更改minimum-idle属性,而不是maximum-pool-size

spring.datasource.hikari.minimum-idle=5

maximum-pool-size的默认值为10,而minimum-idle的默认值与max-pool-size相同。将其更改为小于max-pool-size的值对我有用。

我的直觉是,应用程序在并行执行测试时会尝试与数据库建立大量连接。但是,这些连接使用的时间很短,并且一个连接可以很容易地被多个测试实例重用。通过将minimum-idle属性指定为小于最大池大小的值,我们告诉HikariCP仅在空闲连接数低于该阈值时才添加其他连接。这样可以防止连接池饱和,从而避免遇到太多客户端情况。

但是,HikariCP确实建议 设置此minimum-idle值,以最大程度地提高性能和对峰值需求的响应能力。尝试运行测试时遇到了问题,因此我只为测试环境更改了属性。

我发现Hikari's Github Page很有帮助。在那儿,他们列出了所有这些参数并进行了简要说明。看看吧!

答案 2 :(得分:1)

我尝试了几种解决方案,包括Egemen提出的解决方案,但是它们没有用。

对我来说,解决方案是使用application-test.properties中的此配置来限制连接池的大小:

spring.datasource.maximumPoolSize=2

答案 3 :(得分:0)

我在集成测试 Spring Boot 应用程序和使用 Testcontainers 时遇到了这个问题。我注意到我的连接泄漏导致了这种情况的发生。

IMO 最好的做法是确保所有打开的连接也在您的代码中关闭。