Spring-Boot-2.0.0-M1版本将默认的数据库连接池从tomcat jdbc pool改为了hikari

spring-configuration-metadata.json

spring-boot-autoconfigure-2.0.0.M7.jar!/META-INF/spring-configuration-metadata.json

  1 {
  2       "sourceType": "org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari",
  3       "name": "spring.datasource.hikari",
  4       "sourceMethod": "dataSource(org.springframework.boot.autoconfigure.jdbc.DataSourceProperties)",
  5       "type": "com.zaxxer.hikari.HikariDataSource"
  6     },
  7       {
  8       "sourceType": "com.zaxxer.hikari.HikariDataSource",
  9       "name": "spring.datasource.hikari.allow-pool-suspension",
 10       "type": "java.lang.Boolean"
 11     },
 12     {
 13       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 14       "name": "spring.datasource.hikari.auto-commit",
 15       "type": "java.lang.Boolean"
 16     },
 17     {
 18       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 19       "name": "spring.datasource.hikari.catalog",
 20       "type": "java.lang.String"
 21     },
 22     {
 23       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 24       "name": "spring.datasource.hikari.connection-init-sql",
 25       "type": "java.lang.String"
 26     },
 27     {
 28       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 29       "name": "spring.datasource.hikari.connection-test-query",
 30       "type": "java.lang.String"
 31     },
 32     {
 33       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 34       "name": "spring.datasource.hikari.connection-timeout",
 35       "type": "java.lang.Long"
 36     },
 37     {
 38       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 39       "name": "spring.datasource.hikari.data-source-class-name",
 40       "type": "java.lang.String"
 41     },
 42     {
 43       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 44       "name": "spring.datasource.hikari.data-source-j-n-d-i",
 45       "type": "java.lang.String"
 46     },
 47     {
 48       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 49       "name": "spring.datasource.hikari.data-source-properties",
 50       "type": "java.util.Properties"
 51     },
 52     {
 53       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 54       "name": "spring.datasource.hikari.driver-class-name",
 55       "type": "java.lang.String"
 56     },
 57     {
 58       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 59       "name": "spring.datasource.hikari.health-check-properties",
 60       "type": "java.util.Properties"
 61     },
 62     {
 63       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 64       "name": "spring.datasource.hikari.health-check-registry",
 65       "type": "java.lang.Object"
 66     },
 67     {
 68       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 69       "name": "spring.datasource.hikari.idle-timeout",
 70       "type": "java.lang.Long"
 71     },
 72     {
 73       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 74       "deprecated": true,
 75       "name": "spring.datasource.hikari.initialization-fail-fast", //initializationFailTimeout > 0
 76       "type": "java.lang.Boolean",
 77       "deprecation": {}
 78     },
 79     {
 80       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 81       "name": "spring.datasource.hikari.initialization-fail-timeout",
 82       "type": "java.lang.Long"
 83     },
 84     {
 85       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 86       "name": "spring.datasource.hikari.isolate-internal-queries",
 87       "type": "java.lang.Boolean"
 88     },
 89     {
 90       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 91       "name": "spring.datasource.hikari.jdbc-url",
 92       "type": "java.lang.String"
 93     },
 94     {
 95       "sourceType": "com.zaxxer.hikari.HikariDataSource",
 96       "deprecated": true,
 97       "name": "spring.datasource.hikari.jdbc4-connection-test", //废弃
 98       "type": "java.lang.Boolean",
 99       "deprecation": {}
100     },
101     {
102       "sourceType": "com.zaxxer.hikari.HikariDataSource",
103       "name": "spring.datasource.hikari.leak-detection-threshold",
104       "type": "java.lang.Long"
105     },
106     {
107       "sourceType": "com.zaxxer.hikari.HikariDataSource",
108       "name": "spring.datasource.hikari.login-timeout", //在HikariDataSource及PoolBase中
109       "type": "java.lang.Integer"
110     },
111     {
112       "sourceType": "com.zaxxer.hikari.HikariDataSource",
113       "name": "spring.datasource.hikari.max-lifetime",
114       "type": "java.lang.Long"
115     },
116     {
117       "sourceType": "com.zaxxer.hikari.HikariDataSource",
118       "name": "spring.datasource.hikari.maximum-pool-size",
119       "type": "java.lang.Integer"
120     },
121     {
122       "sourceType": "com.zaxxer.hikari.HikariDataSource",
123       "name": "spring.datasource.hikari.metric-registry",
124       "type": "java.lang.Object"
125     },
126     {
127       "sourceType": "com.zaxxer.hikari.HikariDataSource",
128       "name": "spring.datasource.hikari.metrics-tracker-factory",
129       "type": "com.zaxxer.hikari.metrics.MetricsTrackerFactory"
130     },
131     {
132       "sourceType": "com.zaxxer.hikari.HikariDataSource",
133       "name": "spring.datasource.hikari.minimum-idle",
134       "type": "java.lang.Integer"
135     },
136     {
137       "sourceType": "com.zaxxer.hikari.HikariDataSource",
138       "name": "spring.datasource.hikari.password",
139       "type": "java.lang.String"
140     },
141     {
142       "sourceType": "com.zaxxer.hikari.HikariDataSource",
143       "name": "spring.datasource.hikari.pool-name",
144       "type": "java.lang.String"
145     },
146     {
147       "sourceType": "com.zaxxer.hikari.HikariDataSource",
148       "name": "spring.datasource.hikari.read-only",
149       "type": "java.lang.Boolean"
150     },
151     {
152       "sourceType": "com.zaxxer.hikari.HikariDataSource",
153       "name": "spring.datasource.hikari.register-mbeans",
154       "type": "java.lang.Boolean"
155     },
156     {
157       "sourceType": "com.zaxxer.hikari.HikariDataSource",
158       "name": "spring.datasource.hikari.scheduled-executor",
159       "type": "java.util.concurrent.ScheduledExecutorService"
160     },
161     {
162       "sourceType": "com.zaxxer.hikari.HikariDataSource",
163       "deprecated": true,
164       "name": "spring.datasource.hikari.scheduled-executor-service",
165       "type": "java.util.concurrent.ScheduledThreadPoolExecutor",
166       "deprecation": {}
167     },
168     {
169       "sourceType": "com.zaxxer.hikari.HikariDataSource",
170       "name": "spring.datasource.hikari.schema",
171       "type": "java.lang.String"
172     },
173     {
174       "sourceType": "com.zaxxer.hikari.HikariDataSource",
175       "name": "spring.datasource.hikari.transaction-isolation", //transactionIsolationName
176       "type": "java.lang.String"
177     },
178     {
179       "sourceType": "com.zaxxer.hikari.HikariDataSource",
180       "name": "spring.datasource.hikari.username",
181       "type": "java.lang.String"
182     },
183     {
184       "sourceType": "com.zaxxer.hikari.HikariDataSource",
185       "name": "spring.datasource.hikari.validation-timeout",
186       "type": "java.lang.Long"
187     },

 

HikariConfig

HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/HikariConfig.java

@SuppressWarnings({"SameParameterValue", "unused"})
public class HikariConfig implements HikariConfigMXBean
{
   private static final Logger LOGGER = LoggerFactory.getLogger(HikariConfig.class);

   private static final char[] ID_CHARACTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
   private static final long CONNECTION_TIMEOUT = SECONDS.toMillis(30);
   private static final long VALIDATION_TIMEOUT = SECONDS.toMillis(5);
   private static final long IDLE_TIMEOUT = MINUTES.toMillis(10);
   private static final long MAX_LIFETIME = MINUTES.toMillis(30);
   private static final int DEFAULT_POOL_SIZE = 10;
   //......

   /**
    * Default constructor
    */
   public HikariConfig()
   {
      dataSourceProperties = new Properties();
      healthCheckProperties = new Properties();

      minIdle = -1;
      maxPoolSize = -1;
      maxLifetime = MAX_LIFETIME;
      connectionTimeout = CONNECTION_TIMEOUT;
      validationTimeout = VALIDATION_TIMEOUT;
      idleTimeout = IDLE_TIMEOUT;
      initializationFailTimeout = 1;
      isAutoCommit = true;

      String systemProp = System.getProperty("hikaricp.configurationFile");
      if (systemProp != null) {
         loadProperties(systemProp);
      }
   }

   @Override
   public void setConnectionTimeout(long connectionTimeoutMs)
   {
      if (sealed) throw new IllegalStateException("The configuration of the pool is sealed once started.  Use HikariConfigMXBean for runtime changes.");

      if (connectionTimeoutMs == 0) {
         this.connectionTimeout = Integer.MAX_VALUE;
      }
      else if (connectionTimeoutMs < 250) {
         throw new IllegalArgumentException("connectionTimeout cannot be less than 250ms");
      }
      else {
         this.connectionTimeout = connectionTimeoutMs;
      }
   }

   @Override
   public void setIdleTimeout(long idleTimeoutMs)
   {
      if (sealed) throw new IllegalStateException("The configuration of the pool is sealed once started.  Use HikariConfigMXBean for runtime changes.");

      if (idleTimeoutMs < 0) {
         throw new IllegalArgumentException("idleTimeout cannot be negative");
      }
      this.idleTimeout = idleTimeoutMs;
   }

   @Override
   public void setMaximumPoolSize(int maxPoolSize)
   {
      if (sealed) throw new IllegalStateException("The configuration of the pool is sealed once started.  Use HikariConfigMXBean for runtime changes.");

      if (maxPoolSize < 1) {
         throw new IllegalArgumentException("maxPoolSize cannot be less than 1");
      }
      this.maxPoolSize = maxPoolSize;
   }

   @Override
   public void setMinimumIdle(int minIdle)
   {
      if (sealed) throw new IllegalStateException("The configuration of the pool is sealed once started.  Use HikariConfigMXBean for runtime changes.");

      if (minIdle < 0) {
         throw new IllegalArgumentException("minimumIdle cannot be negative");
      }
      this.minIdle = minIdle;
   }

   @Override
   public void setValidationTimeout(long validationTimeoutMs)
   {
      if (sealed) throw new IllegalStateException("The configuration of the pool is sealed once started.  Use HikariConfigMXBean for runtime changes.");

      if (validationTimeoutMs < 250) {
         throw new IllegalArgumentException("validationTimeout cannot be less than 250ms");
      }

      this.validationTimeout = validationTimeoutMs;
   }

   public void validate()
   {
      if (poolName == null) {
         poolName = generatePoolName();
      }
      else if (isRegisterMbeans && poolName.contains(":")) {
         throw new IllegalArgumentException("poolName cannot contain ':' when used with JMX");
      }

      // treat empty property as null
      catalog = getNullIfEmpty(catalog);
      connectionInitSql = getNullIfEmpty(connectionInitSql);
      connectionTestQuery = getNullIfEmpty(connectionTestQuery);
      transactionIsolationName = getNullIfEmpty(transactionIsolationName);
      dataSourceClassName = getNullIfEmpty(dataSourceClassName);
      dataSourceJndiName = getNullIfEmpty(dataSourceJndiName);
      driverClassName = getNullIfEmpty(driverClassName);
      jdbcUrl = getNullIfEmpty(jdbcUrl);

      // Check Data Source Options
      if (dataSource != null) {
         if (dataSourceClassName != null) {
            LOGGER.warn("{} - using dataSource and ignoring dataSourceClassName.", poolName);
         }
      }
      else if (dataSourceClassName != null) {
         if (driverClassName != null) {
            LOGGER.error("{} - cannot use driverClassName and dataSourceClassName together.", poolName);
            // NOTE: This exception text is referenced by a Spring Boot FailureAnalyzer, it should not be
            // changed without first notifying the Spring Boot developers.
            throw new IllegalStateException("cannot use driverClassName and dataSourceClassName together.");
         }
         else if (jdbcUrl != null) {
            LOGGER.warn("{} - using dataSourceClassName and ignoring jdbcUrl.", poolName);
         }
      }
      else if (jdbcUrl != null || dataSourceJndiName != null) {
         // ok
      }
      else if (driverClassName != null) {
         LOGGER.error("{} - jdbcUrl is required with driverClassName.", poolName);
         throw new IllegalArgumentException("jdbcUrl is required with driverClassName.");
      }
      else {
         LOGGER.error("{} - dataSource or dataSourceClassName or jdbcUrl is required.", poolName);
         throw new IllegalArgumentException("dataSource or dataSourceClassName or jdbcUrl is required.");
      }

      validateNumerics();

      if (LOGGER.isDebugEnabled() || unitTest) {
         logConfiguration();
      }
   }

   private void validateNumerics()
   {
      if (maxLifetime != 0 && maxLifetime < SECONDS.toMillis(30)) {
         LOGGER.warn("{} - maxLifetime is less than 30000ms, setting to default {}ms.", poolName, MAX_LIFETIME);
         maxLifetime = MAX_LIFETIME;
      }

      if (idleTimeout + SECONDS.toMillis(1) > maxLifetime && maxLifetime > 0) {
         LOGGER.warn("{} - idleTimeout is close to or more than maxLifetime, disabling it.", poolName);
         idleTimeout = 0;
      }

      if (idleTimeout != 0 && idleTimeout < SECONDS.toMillis(10)) {
         LOGGER.warn("{} - idleTimeout is less than 10000ms, setting to default {}ms.", poolName, IDLE_TIMEOUT);
         idleTimeout = IDLE_TIMEOUT;
      }

      if (leakDetectionThreshold > 0 && !unitTest) {
         if (leakDetectionThreshold < SECONDS.toMillis(2) || (leakDetectionThreshold > maxLifetime && maxLifetime > 0)) {
            LOGGER.warn("{} - leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it.", poolName);
            leakDetectionThreshold = 0;
         }
      }

      if (connectionTimeout < 250) {
         LOGGER.warn("{} - connectionTimeout is less than 250ms, setting to {}ms.", poolName, CONNECTION_TIMEOUT);
         connectionTimeout = CONNECTION_TIMEOUT;
      }

      if (validationTimeout < 250) {
         LOGGER.warn("{} - validationTimeout is less than 250ms, setting to {}ms.", poolName, VALIDATION_TIMEOUT);
         validationTimeout = VALIDATION_TIMEOUT;
      }

      if (maxPoolSize < 1) {
         maxPoolSize = (minIdle <= 0) ? DEFAULT_POOL_SIZE : minIdle;
      }

      if (minIdle < 0 || minIdle > maxPoolSize) {
         minIdle = maxPoolSize;
      }
   }
}   

 

可以看到在set方法添加了参数校验,同时在configuration的构造器以及getConnection方法中也调用了validate方法
 1  public HikariDataSource(HikariConfig configuration)
 2    {
 3       configuration.validate();
 4       configuration.copyStateTo(this);
 5       this.seal();
 6 
 7       LOGGER.info("{} - Starting...", configuration.getPoolName());
 8       pool = fastPathPool = new HikariPool(this);
 9       LOGGER.info("{} - Start completed.", configuration.getPoolName());
10    }
11 
12    /** {@inheritDoc} */
13    @Override
14    public Connection getConnection() throws SQLException
15    {
16       if (isClosed()) {
17          throw new SQLException("HikariDataSource " + this + " has been closed.");
18       }
19 
20       if (fastPathPool != null) {
21          return fastPathPool.getConnection();
22       }
23 
24       // See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
25       HikariPool result = pool;
26       if (result == null) {
27          synchronized (this) {
28             result = pool;
29             if (result == null) {
30                validate();
31                LOGGER.info("{} - Starting...", getPoolName());
32                try {
33                   pool = result = new HikariPool(this);
34                   this.seal();
35                }
36                catch (PoolInitializationException pie) {
37                   if (pie.getCause() instanceof SQLException) {
38                      throw (SQLException) pie.getCause();
39                   }
40                   else {
41                      throw pie;
42                   }
43                }
44                LOGGER.info("{} - Start completed.", getPoolName());
45             }
46          }
47       }
48 
49       return result.getConnection();
50    }

 

springboot的autoconfig是采用BeanUtils的反射来初始化HikariDataSource,走的是默认构造器,因此校验就依赖set方法以及后续的getConnection方法。

PoolBase.setLoginTimeout

HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/pool/PoolBase.java

 1   /**
 2     * Set the loginTimeout on the specified DataSource.
 3     *
 4     * @param dataSource the DataSource
 5     */
 6    private void setLoginTimeout(final DataSource dataSource)
 7    {
 8       if (connectionTimeout != Integer.MAX_VALUE) {
 9          try {
10             dataSource.setLoginTimeout(Math.max(1, (int) MILLISECONDS.toSeconds(500L + connectionTimeout)));
11          }
12          catch (Throwable e) {
13             LOGGER.info("{} - Failed to set login timeout for data source. ({})", poolName, e.getMessage());
14          }
15       }
16    }

 

这个在初始化的时候设定了loginTimeout,初始值为Math.max(1, (int) MILLISECONDS.toSeconds(500L + connectionTimeout))

 

springboot的HikariDataSource默认配置的默认值如下

name构造器默认值默认配置validate之后的值validate重置
minIdle -1 10 minIdle<0或者minIdle>maxPoolSize,则被重置为maxPoolSize
maxPoolSize -1 10 如果maxPoolSize小于1,则会被重置。当minIdle<=0被重置为DEFAULT_POOL_SIZE则为10;如果minIdle>0则重置为minIdle的值
maxLifetime MINUTES.toMillis(30) = 1800000 1800000 如果不等于0且小于30秒则会被重置回30分钟
connectionTimeout SECONDS.toMillis(30) = 30000 30000 如果小于250毫秒,则被重置回30秒
validationTimeout SECONDS.toMillis(5) = 5000 5000 如果小于250毫秒,则会被重置回5秒
loginTimeout 10 30 Math.max(1, (int) MILLISECONDS.toSeconds(500L + connectionTimeout)),为connectionTimeout+500ms转为秒数取整 与 1 取最大者
idleTimeout MINUTES.toMillis(10) = 600000 600000 如果idleTimeout+1秒>maxLifetime 且 maxLifetime>0,则会被重置为0;如果idleTimeout!=0且小于10秒,则会被重置为10秒
leakDetectionThreshold 0 0 如果大于0且不是单元测试,则进一步判断:(leakDetectionThreshold < SECONDS.toMillis(2) or (leakDetectionThreshold > maxLifetime && maxLifetime > 0),会被重置为0 . 即如果要生效则必须>0,而且不能小于2秒,而且当maxLifetime > 0时不能大于maxLifetime
initializationFailTimeout 1 1 -
isAutoCommit true true -
isReadOnly false fasle -
isAllowPoolSuspension false false -
isIsolateInternalQueries false false -
isRegisterMbeans false false -
sealed false true 运行启动后这个标志为true,表示不再运行修改
poolName null HikariPool-1 -
catalog null null -
connectionInitSql null null -
connectionTestQuery null null -
dataSourceClassName null null -
schema null null -
transactionIsolationName null null -
dataSource null null -
dataSourceProperties {} {} -
threadFactory null null -
scheduledExecutor null null -
metricsTrackerFactory null null -
metricRegistry null null -
healthCheckRegistry null null -
healthCheckProperties {} {} -

doc

打赏

posted @ 2019-09-30 11:15  gqzdev  阅读(1024)  评论(0编辑  收藏  举报