From a910816eff7bbffeddec7ef090e04a78dd51cdba Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 3 Dec 2011 06:23:00 +0800 Subject: [PATCH] HDDataSource --- pom.xml | 15 ++-- .../alibaba/druid/pool/DruidDataSource.java | 10 ++- .../alibaba/druid/pool/ha/HADataSource.java | 5 -- .../druid/pool/ha/MultiDataSource.java | 81 +++++++++++++++++-- .../pool/ha/MultiDataSourceConnection.java | 2 +- .../druid/pool/ha/cobar/CobarDataSource.java | 40 +++++++++ .../druid/pool/ha/config/ConfigLoader.java | 5 ++ .../pool/ha/config/DruidDataSourceConfig.java | 33 ++++++++ .../pool/ha/config/MultiDataSourceConfig.java | 18 +++++ .../ha/config/URLConnectionConfigLoader.java | 17 ++++ .../valid/DefaultValidDataSourceChecker.java | 72 +++++++++++++++++ .../pool/ha/valid/ValidDataSourceChecker.java | 8 ++ 12 files changed, 284 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/pool/ha/cobar/CobarDataSource.java create mode 100644 src/main/java/com/alibaba/druid/pool/ha/config/ConfigLoader.java create mode 100644 src/main/java/com/alibaba/druid/pool/ha/config/DruidDataSourceConfig.java create mode 100644 src/main/java/com/alibaba/druid/pool/ha/config/MultiDataSourceConfig.java create mode 100644 src/main/java/com/alibaba/druid/pool/ha/config/URLConnectionConfigLoader.java create mode 100644 src/main/java/com/alibaba/druid/pool/ha/valid/DefaultValidDataSourceChecker.java create mode 100644 src/main/java/com/alibaba/druid/pool/ha/valid/ValidDataSourceChecker.java diff --git a/pom.xml b/pom.xml index 2e9e01e378..9e2af213d5 100644 --- a/pom.xml +++ b/pom.xml @@ -190,6 +190,14 @@ 1.6.1 provided + + + + com.alibaba + fastjson + 1.1.11 + provided + mysql @@ -242,11 +250,6 @@ 0.9.1.2 test - - com.alibaba - fastjson - 1.0.6 - test - + \ No newline at end of file diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 3ed969b9ce..03d15d151d 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -329,9 +329,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat lock.unlock(); } } - + @Override public Connection getConnection() throws SQLException { + return getConnection(maxWait); + } + + public Connection getConnection(long maxWaitMillis) throws SQLException { init(); final int maxWaitThreadCount = getMaxWaitThreadCount(); @@ -349,7 +353,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } for (;;) { - PoolableConnection poolalbeConnection = getConnectionInternal(); + PoolableConnection poolalbeConnection = getConnectionInternal(maxWaitMillis); if (isTestOnBorrow()) { boolean validate = testConnectionInternal(poolalbeConnection.getConnection()); @@ -423,7 +427,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } - private PoolableConnection getConnectionInternal() throws SQLException { + private PoolableConnection getConnectionInternal(long maxWait) throws SQLException { PoolableConnection poolalbeConnection; try { diff --git a/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java index 2c3801d356..89ce8e9d25 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java @@ -54,11 +54,6 @@ public class HADataSource extends MultiDataSource implements DataSource { throw new UnsupportedOperationException(); } - @Override - public Connection getConnection() throws SQLException { - return new MultiDataSourceConnection(this, createConnectionId()); - } - public Balancer getBalancer() { return balancer; } diff --git a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java index 3115dd0179..ec428fc27c 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java @@ -4,22 +4,74 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.List; import java.util.Properties; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import com.alibaba.druid.pool.DataSourceAdapter; import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.ha.valid.DefaultValidDataSourceChecker; +import com.alibaba.druid.pool.ha.valid.ValidDataSourceChecker; public abstract class MultiDataSource extends DataSourceAdapter { - private Properties properties = new Properties(); + private Properties properties = new Properties(); - private final AtomicInteger connectionIdSeed = new AtomicInteger(); - private final AtomicInteger statementIdSeed = new AtomicInteger(); + private final AtomicInteger connectionIdSeed = new AtomicInteger(); + private final AtomicInteger statementIdSeed = new AtomicInteger(); + + private ValidDataSourceChecker validDataSourceChecker = new DefaultValidDataSourceChecker(); + private long validDataSourceCheckPeriodMillis = 3000; + + private int schedulerThreadCount = 3; + private ScheduledExecutorService scheduler; + + private boolean inited = false; + private final Lock lock = new ReentrantLock(); public MultiDataSource(){ } + public void init() { + if (inited) { + return; + } + + lock.lock(); + try { + if (inited) { + return; + } + + scheduler = Executors.newScheduledThreadPool(schedulerThreadCount); + scheduler.scheduleAtFixedRate(new ValidTask(), validDataSourceCheckPeriodMillis, + validDataSourceCheckPeriodMillis, TimeUnit.MILLISECONDS); + inited = true; + } finally { + lock.unlock(); + } + } + + public long getValidDataSourceCheckPeriodMillis() { + return validDataSourceCheckPeriodMillis; + } + + public void setValidDataSourceCheckPeriodMillis(long validDataSourceCheckPeriodMillis) { + this.validDataSourceCheckPeriodMillis = validDataSourceCheckPeriodMillis; + } + + public ValidDataSourceChecker getValidDataSourceChecker() { + return validDataSourceChecker; + } + + public void setValidDataSourceChecker(ValidDataSourceChecker validDataSourceChecker) { + this.validDataSourceChecker = validDataSourceChecker; + } + public int createConnectionId() { return connectionIdSeed.getAndIncrement(); } @@ -30,16 +82,31 @@ public abstract class MultiDataSource extends DataSourceAdapter { public abstract List getDataSources(); - public abstract void setDataSources(List dataSources); - public Properties getProperties() { return properties; } - @Override - public abstract Connection getConnection() throws SQLException; + public Connection getConnection() throws SQLException { + init(); + + return new MultiDataSourceConnection(this, createConnectionId()); + } public abstract Connection getConnectionInternal(MultiDataSourceConnection conn, String sql) throws SQLException; public abstract void handleNotAwailableDatasource(DruidDataSource dataSource); + + class ValidTask implements Runnable { + + @Override + public void run() { + for (DruidDataSource dataSource : getDataSources()) { + boolean isValid = validDataSourceChecker.isValid(dataSource); + if (isValid) { + handleNotAwailableDatasource(dataSource); + } + } + } + + } } diff --git a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceConnection.java b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceConnection.java index dd3ee97ff2..6a6210dae6 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceConnection.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceConnection.java @@ -49,7 +49,7 @@ public class MultiDataSourceConnection extends WrapperAdapter implements Connect private Date connectedTime = null; - public MultiDataSourceConnection(HADataSource haDataSource, int id){ + public MultiDataSourceConnection(MultiDataSource haDataSource, int id){ this.haDataSource = haDataSource; this.id = id; } diff --git a/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarDataSource.java b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarDataSource.java new file mode 100644 index 0000000000..ec3ad7d69e --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarDataSource.java @@ -0,0 +1,40 @@ +package com.alibaba.druid.pool.ha.cobar; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.ha.MultiDataSource; +import com.alibaba.druid.pool.ha.MultiDataSourceConnection; + + +public class CobarDataSource extends MultiDataSource { + private List dataSources = new ArrayList(); + + @Override + public List getDataSources() { + return dataSources; + } + + public void setDataSources(List dataSources) { + this.dataSources = dataSources; + } + + @Override + public Connection getConnection() throws SQLException { + return new MultiDataSourceConnection(this, createConnectionId()); + } + + @Override + public Connection getConnectionInternal(MultiDataSourceConnection conn, String sql) throws SQLException { + return null; + } + + @Override + public void handleNotAwailableDatasource(DruidDataSource dataSource) { + + } + +} diff --git a/src/main/java/com/alibaba/druid/pool/ha/config/ConfigLoader.java b/src/main/java/com/alibaba/druid/pool/ha/config/ConfigLoader.java new file mode 100644 index 0000000000..6ef218fa0f --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/config/ConfigLoader.java @@ -0,0 +1,5 @@ +package com.alibaba.druid.pool.ha.config; + +public interface ConfigLoader { + MultiDataSourceConfig load(); +} diff --git a/src/main/java/com/alibaba/druid/pool/ha/config/DruidDataSourceConfig.java b/src/main/java/com/alibaba/druid/pool/ha/config/DruidDataSourceConfig.java new file mode 100644 index 0000000000..c9a1012416 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/config/DruidDataSourceConfig.java @@ -0,0 +1,33 @@ +package com.alibaba.druid.pool.ha.config; + +public class DruidDataSourceConfig { + + private String url; + private String user; + private String password; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/src/main/java/com/alibaba/druid/pool/ha/config/MultiDataSourceConfig.java b/src/main/java/com/alibaba/druid/pool/ha/config/MultiDataSourceConfig.java new file mode 100644 index 0000000000..46886955b6 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/config/MultiDataSourceConfig.java @@ -0,0 +1,18 @@ +package com.alibaba.druid.pool.ha.config; + +import java.util.ArrayList; +import java.util.List; + +public class MultiDataSourceConfig { + + private List dataSources = new ArrayList(); + + public List getDataSources() { + return dataSources; + } + + public void setDataSources(List dataSources) { + this.dataSources = dataSources; + } + +} diff --git a/src/main/java/com/alibaba/druid/pool/ha/config/URLConnectionConfigLoader.java b/src/main/java/com/alibaba/druid/pool/ha/config/URLConnectionConfigLoader.java new file mode 100644 index 0000000000..464321fa07 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/config/URLConnectionConfigLoader.java @@ -0,0 +1,17 @@ +package com.alibaba.druid.pool.ha.config; + +import java.net.URL; + +public class URLConnectionConfigLoader { + + private final URL configServerURL; + + public URLConnectionConfigLoader(URL configServerURL){ + this.configServerURL = configServerURL; + } + + public URL getConfigServerURL() { + return configServerURL; + } + +} diff --git a/src/main/java/com/alibaba/druid/pool/ha/valid/DefaultValidDataSourceChecker.java b/src/main/java/com/alibaba/druid/pool/ha/valid/DefaultValidDataSourceChecker.java new file mode 100644 index 0000000000..beeef9f273 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/valid/DefaultValidDataSourceChecker.java @@ -0,0 +1,72 @@ +package com.alibaba.druid.pool.ha.valid; + +import java.sql.Connection; +import java.sql.Statement; + +import com.alibaba.druid.logging.Log; +import com.alibaba.druid.logging.LogFactory; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.util.JdbcUtils; + +public class DefaultValidDataSourceChecker implements ValidDataSourceChecker { + + private final static Log LOG = LogFactory.getLog(DefaultValidDataSourceChecker.class); + + private long maxWaitMillis = 3000; + + private String validateSql = "SELECT 1"; + + public long getMaxWaitMillis() { + return maxWaitMillis; + } + + public void setMaxWaitMillis(long maxWaitMillis) { + this.maxWaitMillis = maxWaitMillis; + } + + public String getValidateSql() { + return validateSql; + } + + public void setValidateSql(String validateSql) { + this.validateSql = validateSql; + } + + @Override + public boolean isValid(DruidDataSource dataSource) { + Connection conn = null; + + try { + conn = dataSource.getConnection(maxWaitMillis); + + if (conn == null) { + return false; + } + + return isValidConnection(dataSource, conn); + + } catch (Exception ex) { + LOG.error("check datasource valid errror", ex); + } finally { + JdbcUtils.close(conn); + } + + return false; + } + + public boolean isValidConnection(DruidDataSource dataSource, Connection conn) { + Statement stmt = null; + + try { + stmt = conn.createStatement(); + stmt.execute(validateSql); + } catch (Exception ex) { + LOG.error("check datasource valid errror", ex); + } finally { + JdbcUtils.close(stmt); + } + + return true; + } + +} diff --git a/src/main/java/com/alibaba/druid/pool/ha/valid/ValidDataSourceChecker.java b/src/main/java/com/alibaba/druid/pool/ha/valid/ValidDataSourceChecker.java new file mode 100644 index 0000000000..8fcbaf4ecb --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/valid/ValidDataSourceChecker.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.pool.ha.valid; + +import com.alibaba.druid.pool.DruidDataSource; + + +public interface ValidDataSourceChecker { + boolean isValid(DruidDataSource dataSource); +}