首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在一段空闲时间后出现连接关闭错误

在一段空闲时间后出现连接关闭错误
EN

Stack Overflow用户
提问于 2018-05-25 19:25:29
回答 1查看 303关注 0票数 0

我有一个多租户应用程序,其中为每个租户配置了一个数据库和一个主数据库。我加载应用程序中的所有数据源,如下所示:

代码语言:javascript
复制
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource() {

    if(LOGGER.isInfoEnabled())
        LOGGER.info("Loading datasources ...");

    DataSource ds = null;
    JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();

    // load MASTER datasource
    ds = dataSourceLookup.getDataSource(properties.getJndiName());

    // load other TENANTs DB details
    JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
    List<GroupConfig> groupConfigs = jdbcTemplate.query(
            "select * from master.tblTenant where IsActive=1 and ConfigCode in ('DB_URL','DATASOURCE_CLASS','USER_NAME','DB_PASSWORD') order by 2",
            new ResultSetExtractor<List<GroupConfig>>() {

                public List<GroupConfig> extractData(ResultSet rs) throws SQLException, DataAccessException {
                    List<GroupConfig> list = new ArrayList<GroupConfig>();

                    while (rs.next()) {
                        GroupConfig groupConfig = new GroupConfig();

                        groupConfig.setGroupConfigId(rs.getLong(1));
                        groupConfig.setGroupCode(rs.getString(2));
                        groupConfig.setConfigCode(rs.getString(3));
                        groupConfig.setConfigValue(rs.getString(4));
                        groupConfig.setIsActive(rs.getBoolean(5));
                        list.add(groupConfig);
                    }

                    return list;
                }

            });

    int propCount = 1;
    Map<String, Map<String, String>> groups = new HashMap<String, Map<String, String>>();
    Map<String, String> temp = new HashMap<String, String>();

    for (GroupConfig config : groupConfigs) {
        temp.put(config.getConfigCode(), config.getConfigValue());
        if (propCount % 4 == 0) {
            groups.put(config.getGroupCode(), temp);
            temp = new HashMap<String, String>();
        }

        propCount++;
    }

    // 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"));

        //System.out.println(dataSourceBuilder.findType()); //class org.apache.tomcat.jdbc.pool.DataSource

        if (properties.getType() != null) {
            dataSourceBuilder.type(properties.getType());
        }

        if(LOGGER.isInfoEnabled())
            LOGGER.info("Building datasource : "+tenantId);
        resolvedDataSources.put(tenantId, dataSourceBuilder.build());

    }


    resolvedDataSources.put("MASTER", ds);


    MultitenantDataSource dataSource = new MultitenantDataSource();
    dataSource.setTargetDataSources(resolvedDataSources);
    dataSource.setDataSourceLookup(dataSourceLookup);       
    dataSource.afterPropertiesSet();

    if(LOGGER.isInfoEnabled())
        LOGGER.info("Datasources initialization finished !");

    return dataSource;
}

在控制器中,我将各自的数据源设置为(租户数据源类似):

代码语言:javascript
复制
TenantContext.setCurrentTenant("MASTER");

问题:在服务器启动时一切正常(主数据库和租户特定查询),但一旦服务器空闲一段时间(几个小时),租户特定调用开始失败(而主数据库连接仍然正常工作),并出现错误:

JPA无法打开事务的JPA EntityManager;嵌套异常为javax.persistence.PersistenceException:关闭了连接。

请帮我摆脱这个异常。提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2018-06-02 02:59:26

我也得到了问题和解决方案:

为什么租户连接会关闭?,因为spring-boot的自动configurations(@ConfigurationProperties(prefix =“spring.datasource”)没有应用到我用代码创建的租户DataSources上。

tomcat解决方案-I添加了设置连接池属性的新方法:

代码语言:javascript
复制
private DataSource buildDataSource(String driverClass, String url, String user, String pass){

    PoolProperties p = new PoolProperties();
    p.setUrl(url);
    p.setDriverClassName(driverClass);
    p.setUsername(user);
    p.setPassword(pass);
    p.setJmxEnabled(true);
    p.setTestWhileIdle(false);
    p.setTestOnBorrow(true); 
    p.setValidationQuery("SELECT 1");
    p.setTestOnReturn(false);
    p.setValidationInterval(30000);
    p.setTimeBetweenEvictionRunsMillis(30000);
    p.setMaxActive(100);
    p.setInitialSize(10);
    p.setMaxWait(10000);
    p.setRemoveAbandonedTimeout(60);
    p.setMinEvictableIdleTimeMillis(30000);
    p.setMinIdle(10);
    p.setLogAbandoned(true);
    p.setRemoveAbandoned(true);
    DataSource datasource = new DataSource();
    datasource.setPoolProperties(p);

    return  datasource;
}

这解决了我的问题。但是我很好奇是否有一种方法可以在spring-boot中创建对象时应用AutoConfigurations。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50528127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档