From 63ae20662ea9e627ea134e907eb93c4b9e633d13 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 21 Dec 2011 13:19:23 +0800 Subject: [PATCH] ha --- .../alibaba/druid/pool/DruidDataSource.java | 9 +++ .../druid/pool/ha/DataSourceHolder.java | 10 +-- .../alibaba/druid/pool/ha/HADataSource.java | 24 ++++++ .../druid/pool/ha/HADataSourceMBean.java | 12 +++ .../druid/pool/ha/MultiDataSource.java | 77 +++++++++++++++---- .../druid/pool/ha/MultiDataSourceMBean.java | 4 + .../druid/pool/ha/cobar/CobarDataSource.java | 2 + 7 files changed, 116 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 89efcfc81e..e94c982189 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -806,6 +806,15 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat lock.unlock(); } } + + public boolean isBusy() { + lock.lock(); + try { + return this.inited && this.activeCount == maxActive && this.poolingCount == 0; + } finally { + lock.unlock(); + } + } public long getRemoveAbandonedCount() { return removeAbandonedCount; diff --git a/src/main/java/com/alibaba/druid/pool/ha/DataSourceHolder.java b/src/main/java/com/alibaba/druid/pool/ha/DataSourceHolder.java index ae8da73898..8af209aa23 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/DataSourceHolder.java +++ b/src/main/java/com/alibaba/druid/pool/ha/DataSourceHolder.java @@ -20,7 +20,7 @@ public class DataSourceHolder implements Closeable { private transient int weightRegionBegin; - private transient int weightReginEnd; + private transient int weightRegionEnd; public int getWeightRegionBegin() { return weightRegionBegin; @@ -30,12 +30,12 @@ public class DataSourceHolder implements Closeable { this.weightRegionBegin = weightRegionBegin; } - public int getWeightReginEnd() { - return weightReginEnd; + public int getWeightRegionEnd() { + return weightRegionEnd; } - public void setWeightReginEnd(int weightReginEnd) { - this.weightReginEnd = weightReginEnd; + public void setWeightRegionEnd(int weightReginEnd) { + this.weightRegionEnd = weightReginEnd; } public DataSourceHolder(DruidDataSource dataSource){ 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 391cb5bd54..5ed4f01f80 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java @@ -114,6 +114,30 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean, return slave.getUrl(); } + + public int getMasterWeight() { + return master.getWeight(); + } + + public int getSlaveWeight() { + return slave.getWeight(); + } + + public int getMasterWeightRegionBegin() { + return master.getWeightRegionBegin(); + } + + public int getMasterWeightRegionEnd() { + return master.getWeightRegionEnd(); + } + + public int getSlaveWeightRegionBegin() { + return slave.getWeightRegionBegin(); + } + + public int getSlaveWeightRegionEnd() { + return slave.getWeightRegionEnd(); + } public boolean isSlaveEnable() { if (slave == null) { diff --git a/src/main/java/com/alibaba/druid/pool/ha/HADataSourceMBean.java b/src/main/java/com/alibaba/druid/pool/ha/HADataSourceMBean.java index 815fd407c7..adf3b4b957 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/HADataSourceMBean.java +++ b/src/main/java/com/alibaba/druid/pool/ha/HADataSourceMBean.java @@ -28,4 +28,16 @@ public interface HADataSourceMBean extends MultiDataSourceMBean { boolean isMasterFail(); boolean isSlaveFail(); + + int getMasterWeight(); + + int getSlaveWeight(); + + int getMasterWeightRegionBegin(); + + int getMasterWeightRegionEnd(); + + int getSlaveWeightRegionBegin(); + + int getSlaveWeightRegionEnd(); } 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 79bea24c32..c5317675dc 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java @@ -44,6 +44,9 @@ public abstract class MultiDataSource extends DataSourceAdapter implements Multi private final AtomicLong configLoadCount = new AtomicLong(); private final AtomicLong failureDetectCount = new AtomicLong(); + private final AtomicLong busySkipCount = new AtomicLong(); + private final AtomicLong retryGetConnectionCount = new AtomicLong(); + protected DataSourceFailureDetecter validDataSourceChecker = new DefaultDataSourceFailureDetecter(); private long failureDetectPeriodMillis = 3000; private long configLoadPeriodMillis = 1000 * 60; @@ -209,14 +212,18 @@ public abstract class MultiDataSource extends DataSourceAdapter implements Multi } public void failureDetect() { + int changeCount = 0; for (DataSourceHolder dataSourceHolder : getDataSources().values()) { - boolean isValid = validDataSourceChecker.isValid(dataSourceHolder.getDataSource()); - if (!isValid) { - dataSourceHolder.setFail(true); - } else { - dataSourceHolder.setFail(false); + boolean isFail = !validDataSourceChecker.isValid(dataSourceHolder.getDataSource()); + + if (isFail != dataSourceHolder.isFail()) { + dataSourceHolder.setFail(isFail); + changeCount++; } } + if (changeCount != 0) { + computeTotalWeight(); + } } protected ScheduledExecutorService getScheduler() { @@ -268,9 +275,14 @@ public abstract class MultiDataSource extends DataSourceAdapter implements Multi public void computeTotalWeight() { int totalWeight = 0; for (DataSourceHolder holder : this.dataSources.values()) { + if (!holder.isEnable()) { + holder.setWeightRegionBegin(-1); + holder.setWeightRegionEnd(-1); + continue; + } holder.setWeightRegionBegin(totalWeight); totalWeight += holder.getWeight(); - holder.setWeightReginEnd(totalWeight); + holder.setWeightRegionEnd(totalWeight); } this.totalWeight = totalWeight; } @@ -283,21 +295,44 @@ public abstract class MultiDataSource extends DataSourceAdapter implements Multi public MultiConnectionHolder getConnectionInternal(MultiDataSourceConnection multiConn, String sql) throws SQLException { - int randomNumber = random.nextInt(totalWeight); DataSourceHolder dataSource = null; - DataSourceHolder first = null; - for (DataSourceHolder item : this.dataSources.values()) { - if (first == null) { - first = item; + final int MAX_RETRY = 10; + for (int i = 0; i < MAX_RETRY; ++i) { + int randomNumber = random.nextInt(totalWeight); + DataSourceHolder first = null; + + boolean needRetry = false; + for (DataSourceHolder item : this.dataSources.values()) { + if (first == null) { + first = item; + } + if (randomNumber >= item.getWeightRegionBegin() && randomNumber < item.getWeightRegionEnd()) { + if (!item.isEnable()) { + needRetry = true; + break; + } + + if (item.getDataSource().isBusy()) { + busySkipCount.incrementAndGet(); + needRetry = true; + break; + } + + dataSource = item; + } } - if (randomNumber >= item.getWeightRegionBegin() && randomNumber < item.getWeightReginEnd()) { - dataSource = item; + + if (needRetry) { + retryGetConnectionCount.incrementAndGet(); + continue; } - } - if (dataSource == null) { - dataSource = first; + + if (dataSource == null) { + dataSource = first; + } + break; } return dataSource.getConnection(); @@ -305,6 +340,14 @@ public abstract class MultiDataSource extends DataSourceAdapter implements Multi public void handleNotAwailableDatasource(DataSourceHolder dataSourceHolder) { } + + public long getRetryGetConnectionCount() { + return retryGetConnectionCount.get(); + } + + public long getBusySkipCount() { + return busySkipCount.get(); + } public String[] getDataSourceNames() { return this.dataSources.keySet().toArray(new String[this.dataSources.size()]); @@ -358,7 +401,7 @@ public abstract class MultiDataSource extends DataSourceAdapter implements Multi public long getConfigLoadCount() { return configLoadCount.get(); } - + public long getFailureDetectCount() { return failureDetectCount.get(); } diff --git a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceMBean.java b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceMBean.java index 86c1e5806f..30a4659010 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceMBean.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceMBean.java @@ -19,4 +19,8 @@ public interface MultiDataSourceMBean { long getConfigLoadCount(); long getFailureDetectCount(); + + long getRetryGetConnectionCount(); + + long getBusySkipCount(); } 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 index 1a74993625..cf162214b1 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarDataSource.java @@ -76,6 +76,8 @@ public class CobarDataSource extends MultiDataSource { if (CobarConfigLoader.isCobar(url)) { this.setConfigLoader(new CobarConfigLoader(this)); + + this.getConfigLoader().load(); } else { DataSourceHolder holder = createDataSourceHolder(this.url, 1); this.addDataSource("master", holder);