From 09ca0375b29e6ff78351b82f7158dd4119545a9b Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 17 Jul 2011 10:26:28 +0000 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81HA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.alibabatech.com/svn/druid/trunk@469 b9813039-fb51-4c41-a8b9-e21c2acb5095 --- .../alibaba/druid/pool/ha/HADataSource.java | 69 +----------------- .../druid/pool/ha/MultiDataSource.java | 2 + .../pool/ha/MultiDataSourceConnection.java | 2 +- .../druid/pool/ha/balance/Balancer.java | 3 +- .../pool/ha/balance/RoundRobinBlancer.java | 73 +++++++++++++++++-- .../druid/pool/ha/balance/SimpleBalancer.java | 57 +++++++++++++++ 6 files changed, 133 insertions(+), 73 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/pool/ha/balance/SimpleBalancer.java 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 3bccbc13c3..975f821a99 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/HADataSource.java @@ -6,22 +6,15 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicInteger; import javax.sql.DataSource; -import com.alibaba.druid.logging.Log; -import com.alibaba.druid.logging.LogFactory; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.ha.balance.Balancer; import com.alibaba.druid.pool.ha.balance.RoundRobinBlancer; public class HADataSource extends MultiDataSource implements DataSource { - private final static Log LOG = LogFactory.getLog(HADataSource.class); - - private final AtomicInteger indexErrorCount = new AtomicInteger(); - protected ArrayList dataSources = new ArrayList(); protected final List notAvailableDatasources = new CopyOnWriteArrayList(); @@ -52,71 +45,17 @@ public class HADataSource extends MultiDataSource implements DataSource { this.balancer = balancer; } - protected int indexFor(MultiDataSourceConnection connection, String sql) throws SQLException { - return balancer.indexFor(connection, sql); + public Connection getConnectionInternal(MultiDataSourceConnection connection, String sql) throws SQLException { + return this.balancer.getConnection(connection, sql); } - public Connection getConnectionInternal(MultiDataSourceConnection multiDataSourceConnection, String sql) throws SQLException { - - int tryCount = 0; - - for (;;) { - int size = dataSources.size(); - - if (size == 0) { - throw new SQLException("can not get connection, no availabe datasources"); - } - - int index = indexFor(multiDataSourceConnection, sql); - - DruidDataSource dataSource = null; - - try { - // 处理并发时的错误 - dataSource = dataSources.get(index); - } catch (Exception ex) { - indexErrorCount.incrementAndGet(); - if (LOG.isDebugEnabled()) { - LOG.debug("getDataSource error, index : " + index, ex); - } - continue; - } - - assert dataSource != null; - - if (!dataSource.isEnable()) { - handleNotAwailableDatasource(dataSource); - continue; - } - - Connection conn = null; - - try { - tryCount++; - conn = dataSource.getConnection(); - } catch (SQLException ex) { - LOG.error("getConnection error", ex); - - if (tryCount >= size) { - throw ex; - } - - continue; - } - - return conn; - } - } - - void handleNotAwailableDatasource(DruidDataSource dataSource) { + public void handleNotAwailableDatasource(DruidDataSource dataSource) { boolean removed = dataSources.remove(dataSource); if (removed) { notAvailableDatasources.add(dataSource); } } - public long getIndexErrorCount() { - return indexErrorCount.get(); - } + } 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 ce4a69b79f..c4ac2bb97a 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java @@ -41,4 +41,6 @@ public abstract class MultiDataSource extends DataSourceAdapter { public abstract Connection getConnection() throws SQLException; public abstract Connection getConnectionInternal(MultiDataSourceConnection conn, String sql) throws SQLException; + + public abstract void handleNotAwailableDatasource(DruidDataSource 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 e6ea3bc8d1..9b2e4d70c4 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceConnection.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourceConnection.java @@ -51,7 +51,7 @@ public class MultiDataSourceConnection extends WrapperAdapter implements Connect this.haDataSource = haDataSource; this.id = id; } - + public void checkConnection(String sql) throws SQLException { if (conn == null) { conn = haDataSource.getConnectionInternal(this, sql); 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 463526529f..d1a77abc8e 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 @@ -1,9 +1,10 @@ package com.alibaba.druid.pool.ha.balance; +import java.sql.Connection; import java.sql.SQLException; import com.alibaba.druid.pool.ha.MultiDataSourceConnection; public interface Balancer { - int indexFor(MultiDataSourceConnection connection, String sql) throws SQLException; + Connection 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 c1bec11ae9..4735ff5111 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 @@ -1,20 +1,81 @@ package com.alibaba.druid.pool.ha.balance; +import java.sql.Connection; import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicInteger; +import com.alibaba.druid.logging.Log; +import com.alibaba.druid.logging.LogFactory; +import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.ha.MultiDataSource; import com.alibaba.druid.pool.ha.MultiDataSourceConnection; public class RoundRobinBlancer implements Balancer { - @Override - public int indexFor(MultiDataSourceConnection connection, String sql) throws SQLException { - MultiDataSource dataSource = connection.getHaDataSource(); + private final static Log LOG = LogFactory.getLog(RoundRobinBlancer.class); - int size = dataSource.getDataSources().size(); - long connectionId = (int) connection.getId(); + private final AtomicInteger indexErrorCount = new AtomicInteger(); + + public RoundRobinBlancer(){ - return (int) (connectionId % size); } + @Override + public Connection getConnection(MultiDataSourceConnection connectionProxy, String sql) throws SQLException { + MultiDataSource multiDataSource = connectionProxy.getHaDataSource(); + + int tryCount = 0; + + for (;;) { + int size = multiDataSource.getDataSources().size(); + long connectionId = (int) connectionProxy.getId(); + + if (size == 0) { + throw new SQLException("can not get connection, no availabe datasources"); + } + + int index = (int) (connectionId % size); + + DruidDataSource dataSource = null; + + try { + // 处理并发时的错误 + dataSource = multiDataSource.getDataSources().get(index); + } catch (Exception ex) { + indexErrorCount.incrementAndGet(); + if (LOG.isDebugEnabled()) { + LOG.debug("getDataSource error, index : " + index, ex); + } + continue; + } + + assert dataSource != null; + + if (!dataSource.isEnable()) { + multiDataSource.handleNotAwailableDatasource(dataSource); + continue; + } + + Connection conn = null; + + try { + tryCount++; + conn = dataSource.getConnection(); + } catch (SQLException ex) { + LOG.error("getConnection error", ex); + + if (tryCount >= size) { + throw ex; + } + + continue; + } + + return conn; + } + } + + public long getIndexErrorCount() { + return indexErrorCount.get(); + } } diff --git a/src/main/java/com/alibaba/druid/pool/ha/balance/SimpleBalancer.java b/src/main/java/com/alibaba/druid/pool/ha/balance/SimpleBalancer.java new file mode 100644 index 0000000000..615d3be767 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/ha/balance/SimpleBalancer.java @@ -0,0 +1,57 @@ +package com.alibaba.druid.pool.ha.balance; + +import java.sql.Connection; +import java.sql.SQLException; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.ha.MultiDataSource; +import com.alibaba.druid.pool.ha.MultiDataSourceConnection; + +public class SimpleBalancer implements Balancer { + + private int maxActive = 8; + + public int getMaxActive() { + return maxActive; + } + + public void setMaxActive(int maxActive) { + this.maxActive = maxActive; + } + + @Override + public Connection getConnection(MultiDataSourceConnection connectionProxy, String sql) throws SQLException { + MultiDataSource multiDataSource = connectionProxy.getHaDataSource(); + + Object[] array = multiDataSource.getDataSources().toArray(); + + DruidDataSource minDataSource = null; + int min = 0; + for (Object item : array) { + DruidDataSource dataSource = (DruidDataSource) item; + + if (!dataSource.isEnable()) { + continue; + } + + int activeCount = dataSource.getActiveCount(); + + if (minDataSource == null || activeCount < min) { + minDataSource = dataSource; + min = activeCount; + } + + if (activeCount >= maxActive) { + continue; + } + + return dataSource.getConnection(); + } + + if (minDataSource != null) { + return minDataSource.getConnection(); + } + + throw new SQLException("can not get connection, no availabe datasources"); + } +}