Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade the database driver version of Mysql to 8 # 3036 #2993 #1868 #3060

Merged
merged 6 commits into from
Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 1999-2018 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 java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

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;

/**
* Properties of external DataSource
*
* @author Nacos
*/
public class ExternalDataSourceProperties {

private final static 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 = 50;

private Integer num;
private List<String> url = new ArrayList<>();
private List<String> user = new ArrayList<>();
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;
}

public void setUrl(List<String> url) {
this.url = url;
}

public void setUser(List<String> user) {
this.user = user;
}

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;
}

/**
*
* @param environment
* {@link Environment}
* @param callback
* Callback function when constructing data source
* @return List of {@link HikariDataSource}
*/
List<HikariDataSource> build(Environment environment, Callback<HikariDataSource> callback) {
List<HikariDataSource> dataSources = new ArrayList<>();
Binder.get(environment).bind("db", Bindable.ofInstance(this));
Preconditions.checkArgument(Objects.nonNull(num), "db.num is null");
Preconditions.checkArgument(CollectionUtils.isNotEmpty(user), "db.user or db.user.[index] is null");
Preconditions.checkArgument(CollectionUtils.isNotEmpty(password), "db.password or db.password.[index] is null");
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(defaultIfNull(user, index, user.get(0)).trim());
ds.setPassword(defaultIfNull(password, index, password.get(0)).trim());
ds.setConnectionTimeout(CONNECTION_TIMEOUT_MS);
ds.setMaximumPoolSize(defaultIfNull(maxPoolSize, index, DEFAULT_MAX_POOL_SIZE));
ds.setMinimumIdle(defaultIfNull(minIdle, index, DEFAULT_MINIMUM_IDLE));
// Check the connection pool every 10 minutes
ds.setValidationTimeout(TimeUnit.MINUTES.toMillis(VALIDATION_TIMEOUT));
ds.setConnectionTestQuery(TEST_QUERY);
dataSources.add(ds);
callback.accept(ds);
}
Preconditions.checkArgument(CollectionUtils.isNotEmpty(dataSources), "no datasource available");
return dataSources;
}

static <T> T defaultIfNull(List<T> collection, int index, T defaultValue) {
paderlol marked this conversation as resolved.
Show resolved Hide resolved
try {
return collection.get(index);
} catch (IndexOutOfBoundsException e) {
return defaultValue;
}
}

interface Callback<T> {

/**
* Perform custom logic
* @param t
*/
void accept(T t);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,34 @@
*/
package com.alibaba.nacos.config.server.service.datasource;

import com.alibaba.nacos.common.utils.ConvertUtils;
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.core.utils.ApplicationUtils;
import com.zaxxer.hikari.HikariDataSource;
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 static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;
import javax.sql.DataSource;

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.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.core.utils.ApplicationUtils;
import com.zaxxer.hikari.HikariDataSource;

/**
* Base data source
Expand All @@ -52,9 +53,7 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {

private static final Logger log = LoggerFactory.getLogger(
ExternalDataSourceServiceImpl.class);
private static final String DEFAULT_MYSQL_DRIVER = "com.mysql.jdbc.Driver";
private static final String MYSQL_HIGH_LEVEL_DRIVER = "com.mysql.cj.jdbc.Driver";
private static String JDBC_DRIVER_NAME;
private final static String JDBC_DRIVER_NAME="com.mysql.cj.jdbc.Driver";

/**
* JDBC执行超时时间, 单位秒
Expand All @@ -78,45 +77,32 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {
private volatile int masterIndex;
private static Pattern ipPattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");

static {
try {
Class.forName(MYSQL_HIGH_LEVEL_DRIVER);
JDBC_DRIVER_NAME = MYSQL_HIGH_LEVEL_DRIVER;
log.info("Use Mysql 8 as the driver");
} catch (ClassNotFoundException e) {
log.info("Use Mysql as the driver");
JDBC_DRIVER_NAME = DEFAULT_MYSQL_DRIVER;
}
}

@PostConstruct

@Override
public void init() {
queryTimeout = ConvertUtils.toInt(System.getProperty("QUERYTIMEOUT"), 3);
jt = new JdbcTemplate();
/**
* 设置最大记录数,防止内存膨胀
*/
// Set the maximum number of records to prevent memory expansion
jt.setMaxRows(50000);
jt.setQueryTimeout(queryTimeout);

testMasterJT = new JdbcTemplate();
testMasterJT.setQueryTimeout(queryTimeout);

testMasterWritableJT = new JdbcTemplate();
/**
* 防止login接口因为主库不可用而rt太长
*/
// Prevent the login interface from being too long because the main library is not available
testMasterWritableJT.setQueryTimeout(1);
/**
* 数据库健康检测
*/

// Database health check

testJTList = new ArrayList<JdbcTemplate>();
isHealthList = new ArrayList<Boolean>();

tm = new DataSourceTransactionManager();
tjt = new TransactionTemplate(tm);
/**
* 事务的超时时间需要与普通操作区分开
* Transaction timeout needs to be distinguished from ordinary operations
*/
tjt.setTimeout(TRANSACTION_QUERY_TIMEOUT);
if (PropertyUtil.isUseExternalDB()) {
Expand All @@ -136,83 +122,28 @@ public void init() {

@Override
public synchronized void reload() throws IOException {
List<HikariDataSource> dblist = new ArrayList<>();
try {
String val = null;
val = ApplicationUtils.getProperty("db.num");
if (null == val) {
throw new IllegalArgumentException("db.num is null");
}
int dbNum = Integer.parseInt(val.trim());

for (int i = 0; i < dbNum; i++) {
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName(JDBC_DRIVER_NAME);

val = ApplicationUtils.getProperty("db.url." + i);
if (null == val) {
fatalLog.error("db.url." + i + " is null");
throw new IllegalArgumentException("db.url." + i + " is null");
}
ds.setJdbcUrl(val.trim());

val = ApplicationUtils.getProperty("db.user." + i, ApplicationUtils.getProperty("db.user"));
if (null == val) {
fatalLog.error("db.user." + i + " is null");
throw new IllegalArgumentException("db.user." + i + " is null");
}
ds.setUsername(val.trim());

val = ApplicationUtils.getProperty("db.password." + i, ApplicationUtils.getProperty("db.password"));
if (null == val) {
fatalLog.error("db.password." + i + " is null");
throw new IllegalArgumentException("db.password." + i + " is null");
}
ds.setPassword(val.trim());

val = ApplicationUtils.getProperty("db.maxPoolSize." + i, ApplicationUtils.getProperty("db.maxPoolSize"));
ds.setMaximumPoolSize(Integer.parseInt(defaultIfNull(val, "20")));

val = ApplicationUtils.getProperty("db.minIdle." + i, ApplicationUtils.getProperty("db.minIdle"));
ds.setMinimumIdle(Integer.parseInt(defaultIfNull(val, "50")));

ds.setConnectionTimeout(3000L);

// 每10分钟检查一遍连接池
ds.setValidationTimeout(TimeUnit.MINUTES.toMillis(10L));
ds.setConnectionTestQuery("SELECT 1 FROM dual");

dblist.add(ds);

JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setQueryTimeout(queryTimeout);
jdbcTemplate.setDataSource(ds);

testJTList.add(jdbcTemplate);
isHealthList.add(Boolean.TRUE);
}

if (dblist == null || dblist.size() == 0) {
throw new RuntimeException("no datasource available");
}

dataSourceList = dblist;
dataSourceList = new ExternalDataSourceProperties()
.build(ApplicationUtils.getEnvironment(), (dataSource) -> {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setQueryTimeout(queryTimeout);
jdbcTemplate.setDataSource(dataSource);
testJTList.add(jdbcTemplate);
isHealthList.add(Boolean.TRUE);
});
new SelectMasterTask().run();
new CheckDBHealthTask().run();
} catch (RuntimeException e) {
fatalLog.error(DB_LOAD_ERROR_MSG, e);
throw new IOException(e);
} finally {
}
}

@Override
public boolean checkMasterWritable() {

testMasterWritableJT.setDataSource(jt.getDataSource());
/**
* 防止login接口因为主库不可用而rt太长
*/
// Prevent the login interface from being too long because the main library is not available
testMasterWritableJT.setQueryTimeout(1);
String sql = " SELECT @@read_only ";

Expand Down Expand Up @@ -255,13 +186,11 @@ public String getHealth() {
for (int i = 0; i < isHealthList.size(); i++) {
if (!isHealthList.get(i)) {
if (i == masterIndex) {
/**
* 主库不健康
*/
// The master is unhealthy
return "DOWN:" + getIpFromUrl(dataSourceList.get(i).getJdbcUrl());
} else {
/**
* 从库不健康
* The slave is unhealthy
*/
return "WARN:" + getIpFromUrl(dataSourceList.get(i).getJdbcUrl());
}
Expand Down
2 changes: 1 addition & 1 deletion distribution/bin/startup.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ if %FUNCTION_MODE% == "naming" (
set "JAVA_OPT=%JAVA_OPT% -Dnacos.functionMode=naming"
)

set "JAVA_OPT=%JAVA_OPT% -Dloader.path=%BASE_DIR%/plugins/health,%BASE_DIR%/plugins/cmdb,%BASE_DIR%/plugins/mysql"
set "JAVA_OPT=%JAVA_OPT% -Dloader.path=%BASE_DIR%/plugins/health,%BASE_DIR%/plugins/cmdb"

set "JAVA_OPT=%JAVA_OPT% -Dnacos.home=%BASE_DIR%"
set "JAVA_OPT=%JAVA_OPT% -jar %BASE_DIR%\target\%SERVER%.jar"
Expand Down
2 changes: 1 addition & 1 deletion distribution/bin/startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ else
JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
fi

JAVA_OPT="${JAVA_OPT} -Dloader.path=${BASE_DIR}/plugins/health,${BASE_DIR}/plugins/cmdb,${BASE_DIR}/plugins/mysql"
JAVA_OPT="${JAVA_OPT} -Dloader.path=${BASE_DIR}/plugins/health,${BASE_DIR}/plugins/cmdb"
JAVA_OPT="${JAVA_OPT} -Dnacos.home=${BASE_DIR}"
JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/target/${SERVER}.jar"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
<httpclient.version>4.5</httpclient.version>
<httpasyncclient.version>4.1.3</httpasyncclient.version>
<async-http-client.version>1.7.17</async-http-client.version>
<mysql-connector-java.version>5.1.34</mysql-connector-java.version>
<mysql-connector-java.version>8.0.13</mysql-connector-java.version>
<derby.version>10.14.2.0</derby.version>
<cglib-nodep.version>2.1</cglib-nodep.version>
<jcip-annotations.version>1.0</jcip-annotations.version>
Expand Down