mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
ha
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package com.alibaba.druid.pool.ha;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
|
||||
public class DataSourceChangedEvent {
|
||||
|
||||
private final DruidDataSource dataSource;
|
||||
|
||||
public DataSourceChangedEvent(DruidDataSource dataSource){
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public DruidDataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.alibaba.druid.pool.DruidDataSource;
|
||||
|
||||
public class DataSourceHolder implements Closeable {
|
||||
|
||||
private final MultiDataSource multiDataSource;
|
||||
private final DruidDataSource dataSource;
|
||||
private boolean enable = true;
|
||||
private final AtomicLong connectCount = new AtomicLong();
|
||||
@@ -48,10 +49,11 @@ public class DataSourceHolder implements Closeable {
|
||||
this.weightRegionEnd = weightReginEnd;
|
||||
}
|
||||
|
||||
public DataSourceHolder(DruidDataSource dataSource){
|
||||
public DataSourceHolder(MultiDataSource multiDataSource, DruidDataSource dataSource){
|
||||
if (dataSource == null) {
|
||||
throw new IllegalArgumentException("dataSource is null");
|
||||
}
|
||||
this.multiDataSource = multiDataSource;
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@@ -72,7 +74,11 @@ public class DataSourceHolder implements Closeable {
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
if (this.enable != enable) {
|
||||
this.enable = enable;
|
||||
|
||||
multiDataSource.afterDataSourceChanged(null);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFail() {
|
||||
@@ -80,7 +86,10 @@ public class DataSourceHolder implements Closeable {
|
||||
}
|
||||
|
||||
public void setFail(boolean fail) {
|
||||
this.fail = fail;
|
||||
if (this.fail != fail) {
|
||||
this.fail = fail;
|
||||
multiDataSource.afterDataSourceChanged(null);
|
||||
}
|
||||
}
|
||||
|
||||
public DruidDataSource getDataSource() {
|
||||
|
||||
@@ -24,11 +24,11 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean,
|
||||
master.resetState();
|
||||
slave.resetState();
|
||||
}
|
||||
|
||||
|
||||
public boolean isMasterWritable() {
|
||||
return master != null && master.isWritable();
|
||||
}
|
||||
|
||||
|
||||
public boolean isSlaveWritable() {
|
||||
return slave != null && slave.isWritable();
|
||||
}
|
||||
@@ -44,17 +44,17 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean,
|
||||
public DataSourceHolder getMaster() {
|
||||
return master;
|
||||
}
|
||||
|
||||
|
||||
public void restartMaster() {
|
||||
this.restartDataSource("master");
|
||||
}
|
||||
|
||||
|
||||
public void restartSlave() {
|
||||
this.restartDataSource("slave");
|
||||
}
|
||||
|
||||
public DataSourceHolder setMaster(DruidDataSource master) {
|
||||
DataSourceHolder holder = new DataSourceHolder(master);
|
||||
DataSourceHolder holder = new DataSourceHolder(this, master);
|
||||
this.setMaster(holder);
|
||||
return holder;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean,
|
||||
}
|
||||
|
||||
public DataSourceHolder setSlave(DruidDataSource slave) {
|
||||
DataSourceHolder holder = new DataSourceHolder(slave);
|
||||
DataSourceHolder holder = new DataSourceHolder(this, slave);
|
||||
this.setSlave(holder);
|
||||
return holder;
|
||||
}
|
||||
@@ -86,20 +86,20 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean,
|
||||
|
||||
return master.isEnable();
|
||||
}
|
||||
|
||||
|
||||
public boolean isMasterFail() {
|
||||
if (master == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return master.isFail();
|
||||
}
|
||||
|
||||
|
||||
public boolean isSlaveFail() {
|
||||
if (slave == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return slave.isFail();
|
||||
}
|
||||
|
||||
@@ -109,8 +109,7 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean,
|
||||
}
|
||||
|
||||
master.setEnable(value);
|
||||
|
||||
this.computeTotalWeight();
|
||||
|
||||
}
|
||||
|
||||
public String getMasterUrl() {
|
||||
@@ -128,27 +127,27 @@ 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();
|
||||
}
|
||||
@@ -167,8 +166,6 @@ public class HADataSource extends MultiDataSource implements HADataSourceMBean,
|
||||
}
|
||||
|
||||
slave.setEnable(value);
|
||||
|
||||
this.computeTotalWeight();
|
||||
}
|
||||
|
||||
public void switchMasterSlave() {
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.alibaba.druid.pool.ha.valid.DataSourceFailureDetecter;
|
||||
import com.alibaba.druid.pool.ha.valid.DefaultDataSourceFailureDetecter;
|
||||
import com.alibaba.druid.proxy.jdbc.DataSourceProxy;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import com.alibaba.druid.util.ThreadLocalRandom;
|
||||
|
||||
public class MultiDataSource extends DataSourceAdapter implements MultiDataSourceMBean, DataSourceProxy {
|
||||
|
||||
@@ -75,8 +74,6 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
|
||||
private String name;
|
||||
|
||||
private int totalWeight = 0;
|
||||
|
||||
private ConfigLoader configLoader;
|
||||
|
||||
private int maxPoolSize = 50;
|
||||
@@ -122,10 +119,6 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
this.configLoader = configLoader;
|
||||
}
|
||||
|
||||
public int getTotalWeight() {
|
||||
return totalWeight;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if (name == null) {
|
||||
return "HADataSource-" + System.identityHashCode(this);
|
||||
@@ -176,6 +169,8 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
return;
|
||||
}
|
||||
|
||||
this.balancer.init(this);
|
||||
|
||||
initInternal();
|
||||
|
||||
scheduler = Executors.newScheduledThreadPool(schedulerThreadCount);
|
||||
@@ -259,7 +254,7 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
}
|
||||
}
|
||||
if (changeCount != 0) {
|
||||
computeTotalWeight();
|
||||
afterDataSourceChanged(null);
|
||||
}
|
||||
|
||||
failureDetectCount.incrementAndGet();
|
||||
@@ -304,7 +299,7 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
public void addDataSource(String name, DataSourceHolder dataSourceHolder) {
|
||||
dataSources.put(name, dataSourceHolder);
|
||||
|
||||
this.computeTotalWeight();
|
||||
afterDataSourceChanged(null);
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
@@ -315,20 +310,7 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
return activeCount;
|
||||
}
|
||||
|
||||
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.setWeightRegionEnd(totalWeight);
|
||||
}
|
||||
this.totalWeight = totalWeight;
|
||||
|
||||
public void notFailSignal() {
|
||||
lock.lock();
|
||||
try {
|
||||
notFail.signalAll();
|
||||
@@ -337,6 +319,10 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
}
|
||||
}
|
||||
|
||||
public void afterDataSourceChanged(Object event) {
|
||||
this.balancer.afterDataSourceChanged(null);
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
init();
|
||||
|
||||
@@ -368,14 +354,6 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
}
|
||||
}
|
||||
|
||||
public int produceRandomNumber() {
|
||||
if (totalWeight == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ThreadLocalRandom.current().nextInt(totalWeight);
|
||||
}
|
||||
|
||||
public MultiConnectionHolder getRealConnection(MultiDataSourceConnection multiConn, String sql) throws SQLException {
|
||||
return balancer.getConnection(multiConn, sql);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ public interface MultiDataSourceMBean {
|
||||
|
||||
long getBusySkipCount();
|
||||
|
||||
int getTotalWeight();
|
||||
|
||||
long getFailureDetectPeriodMillis();
|
||||
|
||||
long getConfigLoadPeriodMillis();
|
||||
@@ -33,6 +31,4 @@ public interface MultiDataSourceMBean {
|
||||
long getActiveCount();
|
||||
|
||||
int getMaxPoolSize();
|
||||
|
||||
int produceRandomNumber();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ package com.alibaba.druid.pool.ha.balance;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.alibaba.druid.pool.ha.MultiConnectionHolder;
|
||||
import com.alibaba.druid.pool.ha.MultiDataSource;
|
||||
import com.alibaba.druid.pool.ha.MultiDataSourceConnection;
|
||||
|
||||
public interface Balancer {
|
||||
void init(MultiDataSource dataSource);
|
||||
void afterDataSourceChanged(Object event);
|
||||
MultiConnectionHolder getConnection(MultiDataSourceConnection connectionProxy, String sql) throws SQLException;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,24 @@ public class RoundRobinBlancer implements Balancer {
|
||||
|
||||
private final AtomicInteger indexErrorCount = new AtomicInteger();
|
||||
|
||||
private MultiDataSource multiDataSource;
|
||||
|
||||
public RoundRobinBlancer(){
|
||||
|
||||
}
|
||||
|
||||
public void afterDataSourceChanged(Object event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(MultiDataSource multiDataSource) {
|
||||
this.multiDataSource = multiDataSource;
|
||||
}
|
||||
|
||||
public MultiDataSource getMultiDataSource() {
|
||||
return multiDataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiConnectionHolder getConnection(MultiDataSourceConnection connectionProxy, String sql)
|
||||
@@ -46,18 +61,18 @@ public class RoundRobinBlancer implements Balancer {
|
||||
if (!item.isEnable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (first == null) {
|
||||
first = item;
|
||||
}
|
||||
|
||||
|
||||
if (itemIndex == index) {
|
||||
dataSource = item;
|
||||
break;
|
||||
}
|
||||
itemIndex++;
|
||||
}
|
||||
|
||||
|
||||
if (dataSource == null) {
|
||||
dataSource = first;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,47 @@ import com.alibaba.druid.pool.ha.DataSourceHolder;
|
||||
import com.alibaba.druid.pool.ha.MultiConnectionHolder;
|
||||
import com.alibaba.druid.pool.ha.MultiDataSource;
|
||||
import com.alibaba.druid.pool.ha.MultiDataSourceConnection;
|
||||
import com.alibaba.druid.util.ThreadLocalRandom;
|
||||
|
||||
public class WeightBalancer implements Balancer {
|
||||
|
||||
private MultiDataSource multiDataSource;
|
||||
private int totalWeight = 0;
|
||||
|
||||
@Override
|
||||
public void init(MultiDataSource multiDataSource) {
|
||||
this.multiDataSource = multiDataSource;
|
||||
}
|
||||
|
||||
public void afterDataSourceChanged(Object event) {
|
||||
computeTotalWeight();
|
||||
}
|
||||
|
||||
public int produceRandomNumber() {
|
||||
if (totalWeight == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ThreadLocalRandom.current().nextInt(totalWeight);
|
||||
}
|
||||
|
||||
public void computeTotalWeight() {
|
||||
int totalWeight = 0;
|
||||
for (DataSourceHolder holder : multiDataSource.getDataSources().values()) {
|
||||
if (!holder.isEnable()) {
|
||||
holder.setWeightRegionBegin(-1);
|
||||
holder.setWeightRegionEnd(-1);
|
||||
continue;
|
||||
}
|
||||
holder.setWeightRegionBegin(totalWeight);
|
||||
totalWeight += holder.getWeight();
|
||||
holder.setWeightRegionEnd(totalWeight);
|
||||
}
|
||||
this.totalWeight = totalWeight;
|
||||
|
||||
multiDataSource.notFailSignal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiConnectionHolder getConnection(MultiDataSourceConnection connectionProxy, String sql)
|
||||
throws SQLException {
|
||||
@@ -27,7 +65,7 @@ public class WeightBalancer implements Balancer {
|
||||
|
||||
final int MAX_RETRY = 10;
|
||||
for (int i = 0; i < MAX_RETRY; ++i) {
|
||||
int randomNumber = multiDataSource.produceRandomNumber();
|
||||
int randomNumber = produceRandomNumber();
|
||||
DataSourceHolder first = null;
|
||||
|
||||
boolean needRetry = false;
|
||||
|
||||
@@ -96,7 +96,7 @@ public class CobarConfigLoader extends URLConnectionConfigLoader implements Conf
|
||||
} else {
|
||||
if (holder.getWeight() != weight) {
|
||||
holder.setWeight(weight);
|
||||
dataSource.computeTotalWeight();
|
||||
dataSource.afterDataSourceChanged(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class CobarConfigLoader extends URLConnectionConfigLoader implements Conf
|
||||
}
|
||||
}
|
||||
if (removeCount != 0) {
|
||||
dataSource.computeTotalWeight();
|
||||
dataSource.afterDataSourceChanged(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ public class CobarDataSource extends MultiDataSource {
|
||||
}
|
||||
dataSource.setProxyFilters(proxyFilters);
|
||||
|
||||
DataSourceHolder holder = new DataSourceHolder(dataSource);
|
||||
DataSourceHolder holder = new DataSourceHolder(this, dataSource);
|
||||
holder.setWeight(weight);
|
||||
return holder;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user