git-svn-id: http://code.alibabatech.com/svn/druid/trunk@469 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
wenshao
2011-07-17 10:26:28 +00:00
parent 6e362a137a
commit 09ca0375b2
6 changed files with 133 additions and 73 deletions
@@ -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<DruidDataSource> dataSources = new ArrayList<DruidDataSource>();
protected final List<DruidDataSource> notAvailableDatasources = new CopyOnWriteArrayList<DruidDataSource>();
@@ -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();
}
}
@@ -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);
}
@@ -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);
@@ -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;
}
@@ -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();
}
}
@@ -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");
}
}