You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启动生成6个Hikari连接池及测试数据库客户端过多问题求助

问题解决:Hikari连接池数量异常与PostgreSQL连接数超限

一、启动时创建6个Hikari连接池的原因及解决方法

原因分析

  1. 数据源方法未被Spring管理为单例Bean:masterDataSource()和readonlyDataSource()没有添加@Bean注解,导致每次调用这两个方法时,都会执行方法体生成全新的数据源对象,而非复用已创建的实例。
  2. 单数据源方法内重复创建连接池:在masterDataSource()和readonlyDataSource()中,先创建一个HikariDataSource实例,随后又将该实例传入connectionPoolDataSource(),通过HikariConfig再次创建新的HikariDataSource,等于每次调用数据源方法会生成2个独立的连接池。
  3. 数据源方法被多次调用:dataSource()方法中,masterDataSource()被调用2次(一次加入targetDataSources,一次设为默认数据源),readonlyDataSource()被调用1次。结合前两点,总连接池数量为:2次master调用×2个池/次 + 1次readonly调用×2个池/次 = 6个,与日志完全匹配。

解决方法

修改数据源配置类,调整逻辑如下:

@Configuration
@Getter
@Setter
public class DataSourcesConfiguration {

    @Autowired
    DataSourceConfig dataSourceConfig;

    private int minimumIdle = 0;
    private int maximumPoolSize = 4;
    private int keepaliveTime = 240000;


    @Bean
    public DataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
                                 @Qualifier("readonlyDataSource") DataSource readonlyDataSource) {

        RoutingDataSource masterSlaveRoutingDataSource = new RoutingDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER, masterDataSource);
        targetDataSources.put(DataSourceType.READONLY, readonlyDataSource);
        masterSlaveRoutingDataSource.setTargetDataSources(targetDataSources);

        log.info("Set default data source as master");
        masterSlaveRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
        return masterSlaveRoutingDataSource;
    }

    @Bean("readonlyDataSource")
    public DataSource readonlyDataSource() {
        log.info("Hit readonlyDataSource() data source");
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(dataSourceConfig.getReadonlyUrl());
        hikariConfig.setMinimumIdle(minimumIdle);
        hikariConfig.setMaximumPoolSize(maximumPoolSize);
        hikariConfig.setKeepaliveTime(keepaliveTime);
        return new HikariDataSource(hikariConfig);
    }

    @Primary
    @Bean("masterDataSource")
    public DataSource masterDataSource() {
        log.info("Hit masterDataSource() data source");
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(dataSourceConfig.getMasterUrl());
        hikariConfig.setMinimumIdle(minimumIdle);
        hikariConfig.setMaximumPoolSize(maximumPoolSize);
        hikariConfig.setKeepaliveTime(keepaliveTime);
        return new HikariDataSource(hikariConfig);
    }
}

修改说明:

  • 给两个数据源方法添加@Bean注解并指定名称,通过@Qualifier注入单例实例,避免重复调用方法创建新对象;
  • 直接通过HikariConfig配置并创建HikariDataSource,移除重复创建连接池的冗余逻辑,每个数据源仅生成1个连接池。

二、测试时PostgreSQL连接数超限(FATAL: sorry, too many clients already)的解决方法

原因分析

该错误是因为PostgreSQL的max_connections最大连接数设置,小于当前应用(含测试)占用的总连接数。测试场景下的常见诱因:

  1. 每个测试类启动独立Spring上下文,每个上下文创建2个连接池(主+只读),若maximumPoolSize为4,多个测试类叠加后连接数快速耗尽;
  2. 测试结束后Spring上下文未及时销毁,连接池未释放数据库连接;
  3. PostgreSQL默认max_connections(通常为100)过小,无法支撑多测试用例的并发连接需求。

解决方法

  1. 复用Spring测试上下文:使用@SpringBootTest时,确保相同配置的测试复用同一上下文,仅在必要时用@DirtiesContext刷新上下文,避免重复创建连接池。
  2. 降低测试环境连接池大小:在测试专用application.yml中减小maximumPoolSize,例如:
spring:
  datasource:
    master:
      hikari:
        maximum-pool-size: 2
    readonly:
      hikari:
        maximum-pool-size: 2
  1. 调整PostgreSQL最大连接数:修改postgresql.conf配置文件,增大max_connections值:
max_connections = 200

修改后重启PostgreSQL生效。
4. 手动释放测试连接:在测试类的@AfterAll方法中,手动关闭数据源连接池,或依赖Spring上下文销毁时自动释放连接。

内容的提问来源于stack exchange,提问作者user19751568

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 12:15:43