mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
ha
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -19,4 +19,8 @@ public interface MultiDataSourceMBean {
|
||||
long getConfigLoadCount();
|
||||
|
||||
long getFailureDetectCount();
|
||||
|
||||
long getRetryGetConnectionCount();
|
||||
|
||||
long getBusySkipCount();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user