【问题标题】:How to simulate lost database connection locally?如何在本地模拟丢失的数据库连接?
【发布时间】:2022-01-07 09:54:24
【问题描述】:

有一个基于 SpringBoot 的应用程序运行在服务器上,它定期插入/更新关系数据库中的记录。

数据库连接是这样设置的:

import org.springframework.context.annotation.Bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import javax.sql.DataSource;

[...]

@Configuration
@EnableConfigurationProperties
public class DbConfigClass {

    [...]

    @Bean(name = "myDataSource")
    @ConfigurationProperties(prefix = "com.mycompany.somedatabase")
    public DataSource dsSomeDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    [...]
}

有时连接会以不规则、不可预测的间隔中断。然后,我得到这样的错误:

java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available,
request timed out after 30001ms.

at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:694)

我需要确保我的应用程序可以处理此类中断。为此,我需要能够在本地重现此行为。

我该怎么做?

我查看了ToxyProxy,这似乎符合我的要求。

但是,我想知道我是否可以用更少的努力模拟这种情况,例如。 G。通过使用 Mockito.spy 修改数据源,使其有时会抛出上述异常。

【问题讨论】:

  • 模拟连接池并编写两个测试:第一个测试连接成功返回,第二个测试连接不可用。

标签: java spring database testing jdbc


【解决方案1】:

【讨论】:

    【解决方案2】:

    找到了一个简单且看似足够好的解决方案:

    首先我创建了一个类,其getConnection 方法在每秒调用一次时抛出一个异常:

    public class ShakyDataSource implements DataSource {
        private final DataSource ds;
        private AtomicLong getConnectionCallsCount = new AtomicLong(1);
        
        public ShakyDataSource(final DataSource ds) {
            this.ds = ds;
        }
        
        @Override
        public Connection getConnection() throws SQLException {
            final long newGetConnectionCallCount = getConnectionCallsCount.incrementAndGet();
            
            if ((newGetConnectionCallCount % 2) == 0) {
                throw new SQLException("Simulated connection failure");
            }
            else {
                return ds.getConnection();
            }
        }
        
        // All other methods of DataSource call corresponding methods of ds
    }
    

    然后我修改了这样的配置:

    import org.springframework.context.annotation.Bean;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import javax.sql.DataSource;
    
    [...]
    
    @Configuration
    @EnableConfigurationProperties
    public class DbConfigClass {
    
        [...]
    
        @Bean(name = "myDataSource")
        @ConfigurationProperties(prefix = "com.mycompany.somedatabase")
        public DataSource dsSomeDataSource() {
            if (SIMULATE_SHAKY_CONNECTION) {
                LOGGER.error("Don't do this in production!");
                return new ShakyDataSource(DataSourceBuilder.create().build());
            }
            return DataSourceBuilder.create().build();
        }
        
        [...]
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-23
      • 2021-05-28
      • 1970-01-01
      • 2013-04-27
      • 1970-01-01
      • 2012-04-06
      • 2011-03-14
      • 2013-06-11
      相关资源
      最近更新 更多