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

多租户应用闲置后租户数据源连接关闭问题求助

解决多租户应用闲置后租户数据源连接关闭问题

你的问题核心是租户数据源的连接池缺少连接存活检测配置,闲置一段时间后数据库主动断开了连接,而主库是通过JNDI获取的,容器(比如Tomcat)默认已经配置了连接池的有效性检测,所以主库连接能保持正常。

问题根源

绝大多数数据库都会主动关闭长时间闲置的连接(比如SQL Server默认连接超时约30分钟),你通过DataSourceBuilder创建的租户数据源,默认没有开启连接池的空闲连接有效性验证和失效连接清理机制。当连接被数据库端断开后,应用层仍持有失效连接,就会抛出The connection is closed异常。

解决方案

在创建租户数据源时,手动添加连接池的存活检测参数,确保连接池定期验证空闲连接状态,自动移除失效连接并创建新连接。以下是修改后的关键代码片段:

// Create TENANT dataSource
Map<Object, Object> resolvedDataSources = new HashMap<Object, Object>();
for (String tenantId : groups.keySet()) {
    Map<String, String> groupKV = groups.get(tenantId);
    DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(this.getClass().getClassLoader());
    dataSourceBuilder.driverClassName(groupKV.get("DATASOURCE_CLASS"))
            .url(groupKV.get("DB_URL"))
            .username(groupKV.get("USER_NAME"))
            .password(groupKV.get("DB_PASSWORD"));

    // 针对Tomcat JDBC Pool配置连接存活检测(你当前使用的正是该连接池)
    if (dataSourceBuilder.getType() == org.apache.tomcat.jdbc.pool.DataSource.class) {
        org.apache.tomcat.jdbc.pool.DataSource tenantDs = (org.apache.tomcat.jdbc.pool.DataSource) dataSourceBuilder.build();
        // SQL Server的连接有效性验证语句
        tenantDs.setValidationQuery("SELECT 1");
        // 空闲时自动验证连接有效性
        tenantDs.setTestWhileIdle(true);
        // 每5分钟执行一次空闲连接检测
        tenantDs.setTimeBetweenEvictionRunsMillis(300000);
        // 连接空闲4分钟后进入检测范围
        tenantDs.setMinEvictableIdleTimeMillis(240000);
        // 每次检测的连接数量
        tenantDs.setNumTestsPerEvictionRun(3);
        resolvedDataSources.put(tenantId, tenantDs);
    } else {
        // 若切换为其他连接池(如HikariCP),需替换为对应配置参数
        resolvedDataSources.put(tenantId, dataSourceBuilder.build());
    }

    if(LOGGER.isInfoEnabled()) LOGGER.info("Building datasource : "+tenantId);
}

额外优化建议

  • 统一连接池配置:让租户数据源的连接池参数和主库JNDI的配置保持一致,避免出现差异化问题
  • 按需启用借取时验证:如果业务对连接可靠性要求极高,可以设置testOnBorrow=true,在获取连接时强制验证有效性,但这会带来轻微性能开销,需根据场景权衡
  • 添加动态刷新机制:可以定时从主库重新加载租户数据源配置,同时刷新连接池,避免配置变更后需要重启服务

补充:如果后续切换到HikariCP连接池,对应的核心参数为connectionTestQuery(验证语句)、keepaliveTime(连接存活检测间隔)、validationTimeout(验证超时时间),需对应调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:45:40