From ec09f1dbb5fc2553b360149cb47b8a15590471c1 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 26 Dec 2011 10:33:28 +0800 Subject: [PATCH] ha --- .../druid/pool/ha/DataSourceChangedEvent.java | 17 ++++++++ .../druid/pool/ha/DataSourceHolder.java | 15 +++++-- .../alibaba/druid/pool/ha/HADataSource.java | 37 ++++++++--------- .../druid/pool/ha/MultiDataSource.java | 40 +++++-------------- .../druid/pool/ha/MultiDataSourceMBean.java | 4 -- .../druid/pool/ha/balance/Balancer.java | 3 ++ .../pool/ha/balance/RoundRobinBlancer.java | 21 ++++++++-- .../druid/pool/ha/balance/WeightBalancer.java | 40 ++++++++++++++++++- .../pool/ha/cobar/CobarConfigLoader.java | 4 +- .../druid/pool/ha/cobar/CobarDataSource.java | 2 +- 10 files changed, 118 insertions(+), 65 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/pool/ha/DataSourceChangedEvent.java diff --git a/src/main/java/com/alibaba/druid/pool/ha/DataSourceChangedEvent.java b/src/main/java/com/alibaba/druid/pool/ha/DataSourceChangedEvent.java new file mode 100644 index 0000000000..57fd5b938c --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/DataSourceChangedEvent.java @@ -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; + } + +} 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 06b883211f..06e75a1694 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/DataSourceHolder.java +++ b/src/main/java/com/alibaba/druid/pool/ha/DataSourceHolder.java @@ -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() { 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 943badae68..8d8364d100 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java @@ -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() { 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 48365ad2b8..031374417b 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java @@ -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); } 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 792f9590c4..95c5857dbc 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceMBean.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceMBean.java @@ -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(); } diff --git a/src/main/java/com/alibaba/druid/pool/ha/balance/Balancer.java b/src/main/java/com/alibaba/druid/pool/ha/balance/Balancer.java index 573942cc74..9be4966055 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/balance/Balancer.java +++ b/src/main/java/com/alibaba/druid/pool/ha/balance/Balancer.java @@ -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; } diff --git a/src/main/java/com/alibaba/druid/pool/ha/balance/RoundRobinBlancer.java b/src/main/java/com/alibaba/druid/pool/ha/balance/RoundRobinBlancer.java index d0178dde98..6bd3e626e8 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/balance/RoundRobinBlancer.java +++ b/src/main/java/com/alibaba/druid/pool/ha/balance/RoundRobinBlancer.java @@ -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; } diff --git a/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java b/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java index d0e02d194a..ca972f816b 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java +++ b/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java @@ -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; diff --git a/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java index b903706cd3..8f0d717ac8 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java +++ b/src/main/java/com/alibaba/druid/pool/ha/cobar/CobarConfigLoader.java @@ -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); } } 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 e73d856a48..1f5fdddd8a 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 @@ -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; }