当前位置:   article > 正文

Hikari连接池1--初始化连接池_hikaridatasource 初始化

hikaridatasource 初始化

基于SpringBoot 2.2.7.RELEASE 依赖的 HikariCP 3.4.3。
源码包中源码和实际Class文件反编译代码有出入,以Class反编译代码为准。
Hikari连接池有两篇
Hikari连接池1–初始化连接池
Hikari连接池2–获取和归还连接
Hikari有两个连接池

private final HikariPool fastPathPool;
private volatile HikariPool pool;
  • 1
  • 2

1、默认构造器

public HikariDataSource() {
    super();
    //将 fastPathPool 置空
    fastPathPool = null;
}
  • 1
  • 2
  • 3
  • 4
  • 5

HikariDataSource 继承 HikariConfig,super 调的是 HikariConfig 的构造方法。

HikariDataSource 也实现了 DataSource 接口

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

使用 HikariDataSource 的默认构造方法创建数据源,多次创建,其父 HikariConfig 只有一个。

并且,这个构造器没有初始化连接池。

2、带参构造器

public HikariDataSource(HikariConfig configuration){
    //校验
    configuration.validate();
    //拷贝属性
    configuration.copyStateTo(this);

    LOGGER.info("{} - Starting...", configuration.getPoolName());
    //创建新的连接池
    pool = fastPathPool = new HikariPool(this);
    LOGGER.info("{} - Start completed.", configuration.getPoolName());
	//设置标志
    this.seal();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

创建 HikariPool

public HikariPool(final HikariConfig config) {
    //调用父类构造器初始化数据源
    super(config);
	//创建bag
    this.connectionBag = new ConcurrentBag<>(this);
    //创建Semaphore锁
    this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK;
	//创建线程池
    this.houseKeepingExecutorService = initializeHouseKeepingExecutorService();
	//初始化连接池,向连接池里放连接
    checkFailFast();

    if (config.getMetricsTrackerFactory() != null) {
        setMetricsTrackerFactory(config.getMetricsTrackerFactory());
    }
    else {
        setMetricRegistry(config.getMetricRegistry());
    }

    setHealthCheckRegistry(config.getHealthCheckRegistry());

    handleMBeans(this, true);

    ThreadFactory threadFactory = config.getThreadFactory();

    final int maxPoolSize = config.getMaximumPoolSize();
    LinkedBlockingQueue<Runnable> addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize);
    this.addConnectionQueueReadOnlyView = unmodifiableCollection(addConnectionQueue);
    this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue, poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
    this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());

    this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService);

    this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(new HouseKeeper(), 100L, housekeepingPeriodMs, MILLISECONDS);

    if (Boolean.getBoolean("com.zaxxer.hikari.blockUntilFilled") && config.getInitializationFailTimeout() > 1) {
        addConnectionExecutor.setCorePoolSize(Math.min(16, Runtime.getRuntime().availableProcessors()));
        addConnectionExecutor.setMaximumPoolSize(Math.min(16, Runtime.getRuntime().availableProcessors()));

        final long startTime = currentTime();
        while (elapsedMillis(startTime) < config.getInitializationFailTimeout() && getTotalConnections() < config.getMinimumIdle()) {
            quietlySleep(MILLISECONDS.toMillis(100));
        }

        addConnectionExecutor.setCorePoolSize(1);
        addConnectionExecutor.setMaximumPoolSize(1);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2.1、初始化数据源

HikariPool的父类

PoolBase(final HikariConfig config) {
    this.config = config;

    this.networkTimeout = UNINITIALIZED;
    this.catalog = config.getCatalog();
    this.schema = config.getSchema();
    this.isReadOnly = config.isReadOnly();
    this.isAutoCommit = config.isAutoCommit();
    this.exceptionOverride = UtilityElf.createInstance(config.getExceptionOverrideClassName(), SQLExceptionOverride.class);
    this.transactionIsolation = UtilityElf.getTransactionIsolation(config.getTransactionIsolation());

    this.isQueryTimeoutSupported = UNINITIALIZED;
    this.isNetworkTimeoutSupported = UNINITIALIZED;
    this.isUseJdbc4Validation = config.getConnectionTestQuery() == null;
    this.isIsolateInternalQueries = config.isIsolateInternalQueries();

    this.poolName = config.getPoolName();
    this.connectionTimeout = config.getConnectionTimeout();
    this.validationTimeout = config.getValidationTimeout();
    this.lastConnectionFailure = new AtomicReference<>();
	//初始化数据源
    initializeDataSource();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

初始化DataSource

private void initializeDataSource() {
    final String jdbcUrl = config.getJdbcUrl();
    final String username = config.getUsername();
    final String password = config.getPassword();
    final String dsClassName = config.getDataSourceClassName();
    final String driverClassName = config.getDriverClassName();
    final String dataSourceJNDI = config.getDataSourceJNDI();
    final Properties dataSourceProperties = config.getDataSourceProperties();
	//DataSource 为空,创建
    DataSource ds = config.getDataSource();
    if (dsClassName != null && ds == null) {
        ds = createInstance(dsClassName, DataSource.class);
        PropertyElf.setTargetFromProperties(ds, dataSourceProperties);
    }
    else if (jdbcUrl != null && ds == null) {//一般会执行这里
        ds = new DriverDataSource(jdbcUrl, driverClassName, dataSourceProperties, username, password);
    }
    else if (dataSourceJNDI != null && ds == null) {
        try {
            InitialContext ic = new InitialContext();
            ds = (DataSource) ic.lookup(dataSourceJNDI);
        } catch (NamingException e) {
            throw new PoolInitializationException(e);
        }
    }

    if (ds != null) {
        //设置登录超时时间
        setLoginTimeout(ds);
        //创建网络超时执行器
        createNetworkTimeoutExecutor(ds, dsClassName, jdbcUrl);
    }

    this.dataSource = ds;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

创建数据源

public DriverDataSource(String jdbcUrl, String driverClassName, Properties properties, String username, String password) {
    this.jdbcUrl = jdbcUrl;
    this.driverProperties = new Properties();

    for (Entry<Object, Object> entry : properties.entrySet()) {
        driverProperties.setProperty(entry.getKey().toString(), entry.getValue().toString());
    }

    if (username != null) {
        driverProperties.put(USER, driverProperties.getProperty("user", username));
    }
    if (password != null) {
        driverProperties.put(PASSWORD, driverProperties.getProperty("password", password));
    }

    if (driverClassName != null) {
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver d = drivers.nextElement();
            if (d.getClass().getName().equals(driverClassName)) {
                driver = d;
                break;
            }
        }

        if (driver == null) {
            LOGGER.warn("Registered driver with driverClassName={} was not found, trying direct instantiation.", driverClassName);
            Class<?> driverClass = null;
            ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
            try {
                if (threadContextClassLoader != null) {
                    try {
                        driverClass = threadContextClassLoader.loadClass(driverClassName);
                        LOGGER.debug("Driver class {} found in Thread context class loader {}", driverClassName, threadContextClassLoader);
                    }
                    catch (ClassNotFoundException e) {
                        LOGGER.debug("Driver class {} not found in Thread context class loader {}, trying classloader {}",
                                     driverClassName, threadContextClassLoader, this.getClass().getClassLoader());
                    }
                }

                if (driverClass == null) {
                    driverClass = this.getClass().getClassLoader().loadClass(driverClassName);
                    LOGGER.debug("Driver class {} found in the HikariConfig class classloader {}", driverClassName, this.getClass().getClassLoader());
                }
            } catch (ClassNotFoundException e) {
                LOGGER.debug("Failed to load driver class {} from HikariConfig class classloader {}", driverClassName, this.getClass().getClassLoader());
            }

            if (driverClass != null) {
                try {
                    //初始化驱动
                    driver = (Driver) driverClass.newInstance();
                } catch (Exception e) {
                    LOGGER.warn("Failed to create instance of driver class {}, trying jdbcUrl resolution", driverClassName, e);
                }
            }
        }
    }

    final String sanitizedUrl = jdbcUrl.replaceAll("([?&;]password=)[^&#;]*(.*)", "$1<masked>$2");
    try {
        if (driver == null) {
            driver = DriverManager.getDriver(jdbcUrl);
            LOGGER.debug("Loaded driver with class name {} for jdbcUrl={}", driver.getClass().getName(), sanitizedUrl);
        }
        else if (!driver.acceptsURL(jdbcUrl)) {
            throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl, " + sanitizedUrl);
        }
    }
    catch (SQLException e) {
        throw new RuntimeException("Failed to get driver instance for jdbcUrl=" + sanitizedUrl, e);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

2.2、初始化连接池

private final ConcurrentBag<PoolEntry> connectionBag;
//com.zaxxer.hikari.pool.HikariPool#checkFailFast
private void checkFailFast() {
    final long initializationTimeout = config.getInitializationFailTimeout();
    if (initializationTimeout < 0) {
        return;
    }

    final long startTime = currentTime();
    do {
        //创建entry
        final PoolEntry poolEntry = createPoolEntry();
        //entry不为空,将entry设置到bag里面,这是初始化时创建的一条连接
        if (poolEntry != null) {
            if (config.getMinimumIdle() > 0) {
                //添加到连接池
                connectionBag.add(poolEntry);
                logger.debug("{} - Added connection {}", poolName, poolEntry.connection);
            }
            else {
                quietlyCloseConnection(poolEntry.close(), "(initialization check complete and minimumIdle is zero)");
            }

            return;
        }

        if (getLastConnectionFailure() instanceof ConnectionSetupException) {
            throwPoolInitializationException(getLastConnectionFailure().getCause());
        }

        quietlySleep(SECONDS.toMillis(1));
    } while (elapsedMillis(startTime) < initializationTimeout);

    if (initializationTimeout > 0) {
        throwPoolInitializationException(getLastConnectionFailure());
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

2.2.1、创建连接

//com.zaxxer.hikari.pool.HikariPool#createPoolEntry
private PoolEntry createPoolEntry() {
    try {
        final PoolEntry poolEntry = newPoolEntry();

        final long maxLifetime = config.getMaxLifetime();
        if (maxLifetime > 0) {
            // variance up to 2.5% of the maxlifetime
            final long variance = maxLifetime > 10_000 ? ThreadLocalRandom.current().nextLong( maxLifetime / 40 ) : 0;
            final long lifetime = maxLifetime - variance;
            poolEntry.setFutureEol(houseKeepingExecutorService.schedule(
                () -> {
                    if (softEvictConnection(poolEntry, "(connection has passed maxLifetime)", false /* not owner */)) {
                        addBagItem(connectionBag.getWaitingThreadCount());
                    }
                },
                lifetime, MILLISECONDS));
        }

        return poolEntry;
    }
    catch (ConnectionSetupException e) {
        if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently
            logger.error("{} - Error thrown while acquiring connection from data source", poolName, e.getCause());
            lastConnectionFailure.set(e);
        }
    }
    catch (Exception e) {
        if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently
            logger.debug("{} - Cannot acquire connection from data source", poolName, e);
        }
    }

    return null;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

创建连接

//com.zaxxer.hikari.pool.PoolBase#newPoolEntry
PoolEntry newPoolEntry() throws Exception {
    return new PoolEntry(newConnection(), this, isReadOnly, isAutoCommit);
}

  • 1
  • 2
  • 3
  • 4
  • 5
2.2.1.1、创建连接
//com.zaxxer.hikari.pool.PoolBase#newConnection
private Connection newConnection() throws Exception {
    final long start = currentTime();

    Connection connection = null;
    try {
        String username = config.getUsername();
        String password = config.getPassword();
		//获取连接
        connection = (username == null) ? dataSource.getConnection() : dataSource.getConnection(username, password);
        if (connection == null) {
            throw new SQLTransientConnectionException("DataSource returned null unexpectedly");
        }
		//设置连接属性
        setupConnection(connection);
        lastConnectionFailure.set(null);
        return connection;
    }
    catch (Exception e) {
        if (connection != null) {
            quietlyCloseConnection(connection, "(Failed to create/setup connection)");
        }
        else if (getLastConnectionFailure() == null) {
            logger.debug("{} - Failed to create/setup connection: {}", poolName, e.getMessage());
        }

        lastConnectionFailure.set(e);
        throw e;
    }
    finally {
        // tracker will be null during failFast check
        if (metricsTracker != null) {
            metricsTracker.recordConnectionCreated(elapsedMillis(start));
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
2.2.1.1.1、获取链接
//com.zaxxer.hikari.util.DriverDataSource#getConnection
public Connection getConnection(final String username, final String password) throws SQLException {
    final Properties cloned = (Properties) driverProperties.clone();
    if (username != null) {
        cloned.put("user", username);
        if (cloned.containsKey("username")) {
            cloned.put("username", username);
        }
    }
    if (password != null) {
        cloned.put("password", password);
    }
	//从数据库驱动获取连接
    return driver.connect(jdbcUrl, cloned);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
2.2.1.2、设置连接属性
//com.zaxxer.hikari.pool.PoolBase#setupConnection
private void setupConnection(final Connection connection) throws ConnectionSetupException {
    try {
        if (networkTimeout == UNINITIALIZED) {
            networkTimeout = getAndSetNetworkTimeout(connection, validationTimeout);
        }
        else {
            setNetworkTimeout(connection, validationTimeout);
        }

        if (connection.isReadOnly() != isReadOnly) {
            connection.setReadOnly(isReadOnly);
        }

        if (connection.getAutoCommit() != isAutoCommit) {
            connection.setAutoCommit(isAutoCommit);
        }
		//检查驱动
        checkDriverSupport(connection);

        if (transactionIsolation != defaultTransactionIsolation) {
            connection.setTransactionIsolation(transactionIsolation);
        }

        if (catalog != null) {
            connection.setCatalog(catalog);
        }

        if (schema != null) {
            connection.setSchema(schema);
        }
		//执行sql
        executeSql(connection, config.getConnectionInitSql(), true);

        setNetworkTimeout(connection, networkTimeout);
    }
    catch (SQLException e) {
        throw new ConnectionSetupException(e);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

执行初始化sql

//com.zaxxer.hikari.pool.PoolBase#executeSql
private void executeSql(final Connection connection, final String sql, final boolean isCommit) throws SQLException {
    if (sql != null) {
        try (Statement statement = connection.createStatement()) {
            // connection was created a few milliseconds before, so set query timeout is omitted (we assume it will succeed)
            //执行sql
            statement.execute(sql);
        }

        if (isIsolateInternalQueries && !isAutoCommit) {
            if (isCommit) {
                connection.commit();
            }
            else {
                connection.rollback();
            }
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
2.2.1.2、创建PoolEntry
PoolEntry(final Connection connection, final PoolBase pool, final boolean isReadOnly, final boolean isAutoCommit) {
    this.connection = connection;
    this.hikariPool = (HikariPool) pool;
    this.isReadOnly = isReadOnly;
    this.isAutoCommit = isAutoCommit;
    this.lastAccessed = currentTime();
    this.openStatements = new FastList<>(Statement.class, 16);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.2.2、向bag添加连接
private final CopyOnWriteArrayList<T> sharedList;
//com.zaxxer.hikari.util.ConcurrentBag#add
public void add(final T bagEntry) {
    if (closed) {
        LOGGER.info("ConcurrentBag has been closed, ignoring add()");
        throw new IllegalStateException("ConcurrentBag has been closed, ignoring add()");
    }
	//添加到sharedList
    sharedList.add(bagEntry);

    // spin until a thread takes it or none are waiting
    while (waiters.get() > 0 && bagEntry.getState() == STATE_NOT_IN_USE && !handoffQueue.offer(bagEntry)) {
        Thread.yield();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/159748
推荐阅读
  

闽ICP备14008679号