Skip to content

Commit

Permalink
Merge pull request alibaba#2723 from digitalsonic/master
Browse files Browse the repository at this point in the history
修复HADataSource的健康检查问题
  • Loading branch information
wenshao authored Sep 14, 2018
2 parents 3633d12 + 54349c6 commit 40ad7f9
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected DruidDataSource create(String name, String url, String username, Strin
HighAvailableDataSource haDataSource) throws SQLException {
DruidDataSource dataSource = new DruidDataSource();

dataSource.setName(name);
dataSource.setName(name + "-" + System.identityHashCode(dataSource));
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
Expand Down Expand Up @@ -122,8 +122,8 @@ protected DruidDataSource create(String name, String url, String username, Strin
private void loadNameList() {
Set<String> names = new HashSet<String>();
for (String n : properties.stringPropertyNames()) {
if (n.contains(".")) {
names.add(n.split("\\.")[0]);
if (n.contains(".url")) {
names.add(n.split("\\.url")[0]);
}
}
if (!names.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,26 @@ public class HighAvailableDataSource extends WrapperAdapter implements DataSourc
private DataSourceSelector selector = new RandomDataSourceSelector(this);
private String dataSourceFile = DEFAULT_DATA_SOURCE_FILE;

private boolean inited = false;

public void init() throws SQLException {
if (inited) {
return;
}
synchronized (this) {
if (inited) {
return;
}
if (dataSourceMap == null || dataSourceMap.isEmpty()) {
dataSourceMap = new DataSourceCreator(dataSourceFile).createMap(this);
}
if (selector == null) {
selector = new RandomDataSourceSelector(this);
}
if (dataSourceMap == null || dataSourceMap.isEmpty()) {
LOG.warn("There is NO DataSource available!!! Please check your configuration.");
}
inited = true;
}
}

Expand All @@ -117,7 +129,12 @@ public void setTargetDataSource(String targetName) {

@Override
public Connection getConnection() throws SQLException {
init();
DataSource dataSource = selector.get();
if (dataSource == null) {
LOG.warn("Can NOT obtain DataSource, return null.");
return null;
}
return dataSource.getConnection();
}

Expand Down Expand Up @@ -145,12 +162,20 @@ public void setSelector(String name) {
}
DataSourceSelector selector = DataSourceSelectorFactory.getSelector(name, this);
if (selector != null) {
this.selector = selector;
setDataSourceSelector(selector);
}
}

public DataSourceSelector getSelector() {
return selector;
public String getSelector() {
return selector == null ? null : selector.getName();
}

public DataSourceSelector getDataSourceSelector() {
return this.selector;
}

public void setDataSourceSelector(DataSourceSelector dataSourceSelector) {
this.selector = dataSourceSelector;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ public interface DataSourceSelector {
DataSource get();
void setTarget(String name);
boolean isSame(String name);
String getName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ public NamedDataSourceSelector(HighAvailableDataSource highAvailableDataSource)

@Override
public boolean isSame(String name) {
return "byName".equalsIgnoreCase(name);
return getName().equalsIgnoreCase(name);
}

@Override
public String getName() {
return "byName";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.ha.HighAvailableDataSource;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;

import javax.sql.DataSource;
import java.util.Collection;
Expand All @@ -33,6 +35,8 @@
* @author DigitalSonic
*/
public class RandomDataSourceSelector implements DataSourceSelector {
private final static Log LOG = LogFactory.getLog(RandomDataSourceSelector.class);

private Random random = new Random();
private List<DataSource> blacklist = new CopyOnWriteArrayList<DataSource>();
private HighAvailableDataSource highAvailableDataSource;
Expand All @@ -41,15 +45,24 @@ public class RandomDataSourceSelector implements DataSourceSelector {

public RandomDataSourceSelector(HighAvailableDataSource highAvailableDataSource) {
this.highAvailableDataSource = highAvailableDataSource;
validateThread = new RandomDataSourceValidateThread(this);
recoverThread = new RandomDataSourceRecoverThread(this);
new Thread(validateThread, "RandomDataSourceSelector-validate-thread").start();
new Thread(recoverThread, "RandomDataSourceSelector-recover-thread").start();
if (!highAvailableDataSource.isTestOnBorrow() && !highAvailableDataSource.isTestOnReturn()) {
validateThread = new RandomDataSourceValidateThread(this);
recoverThread = new RandomDataSourceRecoverThread(this);
new Thread(validateThread, "RandomDataSourceSelector-validate-thread").start();
new Thread(recoverThread, "RandomDataSourceSelector-recover-thread").start();
} else {
LOG.info("testOnBorrow or testOnReturn has been set to true, ignore validateThread");
}
}

@Override
public boolean isSame(String name) {
return "random".equalsIgnoreCase(name);
return getName().equalsIgnoreCase(name);
}

@Override
public String getName() {
return "random";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.JdbcUtils;

import javax.sql.DataSource;
import java.sql.Connection;
Expand Down Expand Up @@ -95,25 +96,28 @@ private void checkAllDataSources() {
private boolean check(String name, DruidDataSource dataSource) {
boolean result = true;
Driver driver = dataSource.getRawDriver();
Properties info = dataSource.getConnectProperties();
String url = dataSource.getRawJdbcUrl();
Properties info = new Properties(dataSource.getConnectProperties());
String username = dataSource.getUsername();
String password = dataSource.getPassword();
String url = dataSource.getUrl(); // We can't use rawUrl here, because the schema maybe set in url.
Connection conn = null;

if (info.getProperty("user") == null && username != null) {
info.setProperty("user", username);
}
if (info.getProperty("password") == null && password != null) {
info.setProperty("password", password);
}
try {
LOG.debug("Validating " + name + " every " + sleepSeconds + " seconds.");
conn = driver.connect(url, info);
dataSource.validateConnection(conn);
} catch (SQLException e) {
LOG.warn("Validation FAILED for " + name + ". Exception: " + e.getMessage());
LOG.warn("Validation FAILED for " + name + " with url [" + url + "] and username ["
+ info.getProperty("user") + "]. Exception: " + e.getMessage());
result = false;
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
LOG.error("Can not close connection for HostAndPort Validation.", e);
}
}
JdbcUtils.close(conn);
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public void tearDown() {

@Test
public void testOneDataSourceFailAndRecover() throws Exception {
((RandomDataSourceSelector) highAvailableDataSource.getSelector()).getValidateThread().setSleepSeconds(3);
((RandomDataSourceSelector) highAvailableDataSource.getSelector()).getRecoverThread().setSleepSeconds(3);
((RandomDataSourceSelector) highAvailableDataSource.getDataSourceSelector()).getValidateThread().setSleepSeconds(3);
((RandomDataSourceSelector) highAvailableDataSource.getDataSourceSelector()).getRecoverThread().setSleepSeconds(3);

Thread.sleep(30 * 1000);

Expand All @@ -40,15 +40,15 @@ public void testOneDataSourceFailAndRecover() throws Exception {
Thread.sleep(10 * 1000);
assertTrue(dataSource.isTestOnReturn());
for (int i = 0; i < 100; i++) {
assertNotEquals(dataSource, highAvailableDataSource.getSelector().get());
assertNotEquals(dataSource, highAvailableDataSource.getDataSourceSelector().get());
}

dataSource.setValidationQuery(null);
Thread.sleep(4 * 1000);
assertFalse(dataSource.isTestOnReturn());
int count = 0;
for (int i = 0; i < 100; i++) {
if (dataSource == highAvailableDataSource.getSelector().get()) {
if (dataSource == highAvailableDataSource.getDataSourceSelector().get()) {
count++;
}
}
Expand All @@ -57,8 +57,8 @@ public void testOneDataSourceFailAndRecover() throws Exception {

@Test
public void testAllDataSourceFail() throws Exception {
((RandomDataSourceSelector) highAvailableDataSource.getSelector()).getValidateThread().setSleepSeconds(3);
((RandomDataSourceSelector) highAvailableDataSource.getSelector()).getRecoverThread().setSleepSeconds(3);
((RandomDataSourceSelector) highAvailableDataSource.getDataSourceSelector()).getValidateThread().setSleepSeconds(3);
((RandomDataSourceSelector) highAvailableDataSource.getDataSourceSelector()).getRecoverThread().setSleepSeconds(3);

Thread.sleep(30 * 1000);

Expand All @@ -73,7 +73,7 @@ public void testAllDataSourceFail() throws Exception {

int[] count = new int[2];
for (int i = 0; i < 100; i++) {
DataSource dataSource = highAvailableDataSource.getSelector().get();
DataSource dataSource = highAvailableDataSource.getDataSourceSelector().get();
if (foo == dataSource) {
count[0]++;
} else if (bar == dataSource) {
Expand Down

0 comments on commit 40ad7f9

Please sign in to comment.