Skip to content

Commit

Permalink
For #3607, #4078, #4170, Datasource pool configuration can be configu…
Browse files Browse the repository at this point in the history
…red. (#4178)

* For #3607, #4078, #4170, Datasource pool configuration.

* Fix ci error.
  • Loading branch information
KomachiSion committed Nov 9, 2020
1 parent cf92d19 commit 6b7fb05
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 101 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.config.server.service.datasource;

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;

import java.util.concurrent.TimeUnit;

/**
* DataSource pool properties.
*
* <p>Nacos server use HikariCP as the datasource pool. So the basic pool properties will based on {@link
* com.zaxxer.hikari.HikariDataSource}.
*
* @author xiweng.yy
*/
public class DataSourcePoolProperties {

public static final long DEFAULT_CONNECTION_TIMEOUT = TimeUnit.SECONDS.toMillis(30L);

public static final long DEFAULT_VALIDATION_TIMEOUT = TimeUnit.SECONDS.toMillis(10L);

public static final int DEFAULT_MAX_POOL_SIZE = 20;

public static final int DEFAULT_MINIMUM_IDLE = 2;

private final HikariDataSource dataSource;

private DataSourcePoolProperties() {
dataSource = new HikariDataSource();
dataSource.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
dataSource.setValidationTimeout(DEFAULT_VALIDATION_TIMEOUT);
dataSource.setMaximumPoolSize(DEFAULT_MAX_POOL_SIZE);
dataSource.setMinimumIdle(DEFAULT_MINIMUM_IDLE);
}

/**
* Build new Hikari config.
*
* @return new hikari config
*/
public static DataSourcePoolProperties build(Environment environment) {
DataSourcePoolProperties result = new DataSourcePoolProperties();
Binder.get(environment).bind("db.pool.config", Bindable.ofInstance(result.getDataSource()));
return result;
}

public void setDriverClassName(final String driverClassName) {
dataSource.setDriverClassName(driverClassName);
}

public void setJdbcUrl(final String jdbcUrl) {
dataSource.setJdbcUrl(jdbcUrl);
}

public void setUsername(final String username) {
dataSource.setUsername(username);
}

public void setPassword(final String password) {
dataSource.setPassword(password);
}

public HikariDataSource getDataSource() {
return dataSource;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,18 @@

package com.alibaba.nacos.config.server.service.datasource;

import static com.alibaba.nacos.common.utils.CollectionUtils.getOrDefault;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import com.google.common.base.Preconditions;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;

import com.google.common.base.Preconditions;
import com.zaxxer.hikari.HikariDataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.alibaba.nacos.common.utils.CollectionUtils.getOrDefault;

/**
* Properties of external DataSource.
Expand All @@ -37,15 +35,7 @@ public class ExternalDataSourceProperties {

private static final String JDBC_DRIVER_NAME = "com.mysql.cj.jdbc.Driver";

public static final long CONNECTION_TIMEOUT_MS = 3000L;

public static final long VALIDATION_TIMEOUT = 10L;

public static final String TEST_QUERY = "SELECT 1 FROM dual";

public static final int DEFAULT_MAX_POOL_SIZE = 20;

public static final int DEFAULT_MINIMUM_IDLE = 20;
private static final String TEST_QUERY = "SELECT 1";

private Integer num;

Expand All @@ -55,10 +45,6 @@ public class ExternalDataSourceProperties {

private List<String> password = new ArrayList<>();

private List<Integer> maxPoolSize = new ArrayList<>();

private List<Integer> minIdle = new ArrayList<>();

public void setNum(Integer num) {
this.num = num;
}
Expand All @@ -75,14 +61,6 @@ public void setPassword(List<String> password) {
this.password = password;
}

public void setMaxPoolSize(List<Integer> maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}

public void setMinIdle(List<Integer> minIdle) {
this.minIdle = minIdle;
}

/**
* Build serveral HikariDataSource.
*
Expand All @@ -99,16 +77,12 @@ List<HikariDataSource> build(Environment environment, Callback<HikariDataSource>
for (int index = 0; index < num; index++) {
int currentSize = index + 1;
Preconditions.checkArgument(url.size() >= currentSize, "db.url.%s is null", index);
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName(JDBC_DRIVER_NAME);
ds.setJdbcUrl(url.get(index).trim());
ds.setUsername(getOrDefault(user, index, user.get(0)).trim());
ds.setPassword(getOrDefault(password, index, password.get(0)).trim());
ds.setConnectionTimeout(CONNECTION_TIMEOUT_MS);
ds.setMaximumPoolSize(getOrDefault(maxPoolSize, index, DEFAULT_MAX_POOL_SIZE));
ds.setMinimumIdle(getOrDefault(minIdle, index, DEFAULT_MINIMUM_IDLE));
// Check the connection pool every 10 minutes
ds.setValidationTimeout(TimeUnit.MINUTES.toMillis(VALIDATION_TIMEOUT));
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(environment);
poolProperties.setDriverClassName(JDBC_DRIVER_NAME);
poolProperties.setJdbcUrl(url.get(index).trim());
poolProperties.setUsername(getOrDefault(user, index, user.get(0)).trim());
poolProperties.setPassword(getOrDefault(password, index, password.get(0)).trim());
HikariDataSource ds = poolProperties.getDataSource();
ds.setConnectionTestQuery(TEST_QUERY);
dataSources.add(ds);
callback.accept(ds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,29 @@

package com.alibaba.nacos.config.server.service.datasource;

import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;
import static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.sql.DataSource;

import com.alibaba.nacos.common.utils.IPUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.IPUtil;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.sys.utils.ApplicationUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;
import static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;

/**
* Base data source.
Expand All @@ -51,10 +47,6 @@
*/
public class ExternalDataSourceServiceImpl implements DataSourceService {

private static final Logger LOGGER = LoggerFactory.getLogger(ExternalDataSourceServiceImpl.class);

private static final String JDBC_DRIVER_NAME = "com.mysql.cj.jdbc.Driver";

/**
* JDBC execute timeout value, unit:second.
*/
Expand Down Expand Up @@ -198,10 +190,6 @@ public String getHealth() {
return "UP";
}

static String defaultIfNull(String value, String defaultValue) {
return null == value ? defaultValue : value;
}

class SelectMasterTask implements Runnable {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@
import com.alibaba.nacos.sys.utils.ApplicationUtils;
import com.alibaba.nacos.sys.utils.DiskUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
Expand All @@ -36,13 +42,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

/**
* local data source.
Expand Down Expand Up @@ -121,7 +120,7 @@ public void cleanAndReopenDerby() throws Exception {
/**
* Restore derby.
*
* @param jdbcUrl jdbcUrl string value.
* @param jdbcUrl jdbcUrl string value.
* @param callable callable.
* @throws Exception exception.
*/
Expand All @@ -145,14 +144,12 @@ private void doDerbyClean() throws Exception {
}

private synchronized void initialize(String jdbcUrl) {
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName(jdbcDriverName);
ds.setJdbcUrl(jdbcUrl);
ds.setUsername(userName);
ds.setPassword(password);
ds.setIdleTimeout(30_000L);
ds.setMaximumPoolSize(80);
ds.setConnectionTimeout(10000L);
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(ApplicationUtils.getEnvironment());
poolProperties.setDriverClassName(jdbcDriverName);
poolProperties.setJdbcUrl(jdbcUrl);
poolProperties.setUsername(userName);
poolProperties.setPassword(password);
HikariDataSource ds = poolProperties.getDataSource();
DataSourceTransactionManager tm = new DataSourceTransactionManager();
tm.setDataSource(ds);
if (jdbcTemplateInit) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.config.server.service.datasource;

import com.zaxxer.hikari.HikariDataSource;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.env.MockEnvironment;

import static org.junit.Assert.assertEquals;

public class DataSourcePoolPropertiesTest {

private static final String JDBC_URL = "jdbc:derby://127.0.0.1:3306/nacos_devtest?characterEncoding=utf8&serverTimezone=UTC";

private static final String JDBC_DRIVER_CLASS_NAME = "org.apache.derby.jdbc.EmbeddedDriver";

private static final String PASSWORD = "nacos";

private static final String USERNAME = "nacos_devtest";

private static final Long CONNECTION_TIMEOUT = 10000L;

private static final Integer MAX_POOL_SIZE = 50;

private MockEnvironment environment;

@Before
public void setUp() throws Exception {
environment = new MockEnvironment();
environment.setProperty("db.user", USERNAME);
environment.setProperty("db.password", PASSWORD);
environment.setProperty("db.pool.config.connectionTimeout", CONNECTION_TIMEOUT.toString());
environment.setProperty("db.pool.config.maximumPoolSize", MAX_POOL_SIZE.toString());
}

@Test
public void testBuild() {
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(environment);
poolProperties.setJdbcUrl(JDBC_URL);
poolProperties.setDriverClassName(JDBC_DRIVER_CLASS_NAME);
poolProperties.setUsername(USERNAME);
poolProperties.setPassword(PASSWORD);
HikariDataSource actual = poolProperties.getDataSource();
assertEquals(JDBC_URL, actual.getJdbcUrl());
assertEquals(JDBC_DRIVER_CLASS_NAME, actual.getDriverClassName());
assertEquals(USERNAME, actual.getUsername());
assertEquals(PASSWORD, actual.getPassword());
assertEquals(CONNECTION_TIMEOUT.longValue(), actual.getConnectionTimeout());
assertEquals(DataSourcePoolProperties.DEFAULT_VALIDATION_TIMEOUT, actual.getValidationTimeout());
assertEquals(MAX_POOL_SIZE.intValue(), actual.getMaximumPoolSize());
assertEquals(DataSourcePoolProperties.DEFAULT_MINIMUM_IDLE, actual.getMinimumIdle());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void externalDatasourceToAssertMinIdle() {
environment.setProperty("db.url.0", JDBC_URL);
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
dataSource.validate();
Assert.assertEquals(dataSource.getMinimumIdle(), ExternalDataSourceProperties.DEFAULT_MINIMUM_IDLE);
Assert.assertEquals(dataSource.getMinimumIdle(), DataSourcePoolProperties.DEFAULT_MINIMUM_IDLE);
}));
Assert.assertEquals(dataSources.size(), 1);
}
Expand Down
Loading

0 comments on commit 6b7fb05

Please sign in to comment.