This commit is contained in:
wenshao
2011-12-09 08:32:10 +08:00
parent b08281a153
commit 4dc2a42405
11 changed files with 366 additions and 89 deletions
@@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;
import javax.management.JMException;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
@@ -194,6 +195,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
private boolean dupCloseLogEnable = true;
private ObjectName objectName;
public boolean isDupCloseLogEnable() {
return dupCloseLogEnable;
@@ -202,7 +204,14 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
public void setDupCloseLogEnable(boolean dupCloseLogEnable) {
this.dupCloseLogEnable = dupCloseLogEnable;
}
public ObjectName getObjectName() {
return objectName;
}
public void setObjectName(ObjectName objectName) {
this.objectName = objectName;
}
public Histogram getTransactionHistogram() {
return transactionHistogram;
@@ -108,8 +108,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
private String initStackTrace;
private ObjectName objectName;
public DruidDataSource(){
}
@@ -117,14 +115,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
return initStackTrace;
}
public ObjectName getObjectName() {
return objectName;
}
public void setObjectName(ObjectName objectName) {
this.objectName = objectName;
}
public boolean isResetStatEnable() {
return resetStatEnable;
}
@@ -703,7 +693,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
for (;;) {
if (poolingCount == 0) {
empty.signal(); // send signal to CreateThread create connection
if (notEmptyWaitThreadCount == 0) {
empty.signal(); // send signal to CreateThread create connection
}
if (estimate <= 0) {
throw new GetConnectionTimeoutException();
@@ -712,9 +704,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
notEmptyWaitThreadCount++;
try {
long startEstimate = estimate;
estimate = notEmpty.awaitNanos(estimate); // signal by
// recycle or
// creator
estimate = notEmpty.awaitNanos(estimate); // signal by recycle or creator
notEmptyWaitCount++;
notEmptyWaitNanos += (startEstimate - estimate);
@@ -17,6 +17,8 @@ package com.alibaba.druid.pool;
import java.util.Date;
import javax.management.ObjectName;
/**
* @author wenshao<szujobs@hotmail.com>
*/
@@ -73,4 +75,6 @@ public interface DruidDataSourceMBean extends DruidAbstractDataSourceMBean {
Date getPoolingPeakTime();
long getErrorCount();
ObjectName getObjectName();
}
@@ -2,9 +2,7 @@ package com.alibaba.druid.pool.ha;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.AbstractList;
import java.util.List;
import java.util.RandomAccess;
import javax.sql.DataSource;
@@ -13,18 +11,15 @@ 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;
import com.alibaba.druid.util.JdbcUtils;
public class HADataSource extends MultiDataSource implements DataSource {
private final static Log LOG = LogFactory.getLog(HADataSource.class);
private final static Log LOG = LogFactory.getLog(HADataSource.class);
protected DruidDataSource master;
protected DruidDataSource slave;
protected DruidDataSource master;
protected DruidDataSource slave;
protected Balancer balancer = new RoundRobinBlancer();
private DataSourceList dataSourceList = new DataSourceList();
protected Balancer balancer = new RoundRobinBlancer();
public HADataSource(){
@@ -35,6 +30,7 @@ public class HADataSource extends MultiDataSource implements DataSource {
}
public void setMaster(DruidDataSource master) {
this.getDataSources().put("master", master);
this.master = master;
}
@@ -43,13 +39,10 @@ public class HADataSource extends MultiDataSource implements DataSource {
}
public void setSlave(DruidDataSource slave) {
this.getDataSources().put("slave", slave);
this.slave = slave;
}
public List<DruidDataSource> getDataSources() {
return dataSourceList;
}
public synchronized void setDataSources(List<DruidDataSource> dataSources) {
throw new UnsupportedOperationException();
}
@@ -77,52 +70,4 @@ public class HADataSource extends MultiDataSource implements DataSource {
}
}
private class DataSourceList extends AbstractList<DruidDataSource> implements RandomAccess, java.io.Serializable {
private static final long serialVersionUID = -2764017481108945198L;
public int size() {
return 2;
}
public Object[] toArray() {
return new DruidDataSource[] { master, slave };
}
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
public DruidDataSource get(int index) {
if (index == 0) {
return master;
}
if (index == 1) {
return slave;
}
throw new IllegalArgumentException("index : " + index);
}
public DruidDataSource set(int index, DruidDataSource element) {
throw new UnsupportedOperationException();
}
public int indexOf(Object o) {
if (o == master) {
return 0;
}
if (o == slave) {
return 1;
}
return -1;
}
public boolean contains(Object o) {
return o == master || o == slave;
}
}
}
@@ -2,8 +2,10 @@ package com.alibaba.druid.pool.ha;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -32,6 +34,8 @@ public abstract class MultiDataSource extends DataSourceAdapter {
private boolean inited = false;
private final Lock lock = new ReentrantLock();
private ConcurrentMap<String, DruidDataSource> dataSources = new ConcurrentHashMap<String, DruidDataSource>();
public MultiDataSource(){
@@ -94,7 +98,9 @@ public abstract class MultiDataSource extends DataSourceAdapter {
return statementIdSeed.incrementAndGet();
}
public abstract List<DruidDataSource> getDataSources();
public Map<String, DruidDataSource> getDataSources() {
return dataSources;
}
public Properties getProperties() {
return properties;
@@ -114,7 +120,7 @@ public abstract class MultiDataSource extends DataSourceAdapter {
@Override
public void run() {
for (DruidDataSource dataSource : getDataSources()) {
for (DruidDataSource dataSource : getDataSources().values()) {
boolean isValid = validDataSourceChecker.isValid(dataSource);
if (isValid) {
handleNotAwailableDatasource(dataSource);
@@ -2,10 +2,48 @@ package com.alibaba.druid.pool.ha.config;
public class DruidDataSourceConfig {
private String name;
private String url;
private String user;
private String username;
private String password;
private int initialSize;
protected int maxActive;
private int minIdle;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getInitialSize() {
return initialSize;
}
public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public String getUrl() {
return url;
}
@@ -14,12 +52,12 @@ public class DruidDataSourceConfig {
this.url = url;
}
public String getUser() {
return user;
public String getUsername() {
return username;
}
public void setUser(String user) {
this.user = user;
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
@@ -5,8 +5,18 @@ import java.util.List;
public class MultiDataSourceConfig {
private String name;
private List<DruidDataSourceConfig> dataSources = new ArrayList<DruidDataSourceConfig>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<DruidDataSourceConfig> getDataSources() {
return dataSources;
}
@@ -1,17 +1,84 @@
package com.alibaba.druid.pool.ha.config;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class URLConnectionConfigLoader {
import com.alibaba.druid.DruidRuntimeException;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.fastjson.JSON;
private final URL configServerURL;
public class URLConnectionConfigLoader implements ConfigLoader {
private URL url;
private int connectTimeout = 1000 * 3;
private int readTimeout;
public URLConnectionConfigLoader(URL configServerURL){
this.configServerURL = configServerURL;
this.url = configServerURL;
}
public URL getConfigServerURL() {
return configServerURL;
public URLConnectionConfigLoader(String url) throws MalformedURLException{
this.url = new URL(url);
}
public URL getURL() {
return url;
}
public void setURL(URL url) {
this.url = url;
}
public int getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public int getReadTimeout() {
return readTimeout;
}
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
@Override
public MultiDataSourceConfig load() {
if (url == null) {
throw new IllegalStateException("configServerURL is null");
}
String responseMessage;
{
HttpURLConnection conn = null;
Reader reader = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
conn.connect();
reader = new InputStreamReader(conn.getInputStream());
responseMessage = JdbcUtils.read(reader);
} catch (Exception e) {
throw new DruidRuntimeException("load config error, url : " + url.toString());
} finally {
JdbcUtils.close(reader);
conn.disconnect();
}
}
MultiDataSourceConfig config = JSON.parseObject(responseMessage, MultiDataSourceConfig.class);
return config;
}
}
@@ -0,0 +1,44 @@
package com.alibaba.druid.pool;
import java.sql.Connection;
import com.alibaba.druid.pool.vendor.MySqlExceptionSorter;
import com.alibaba.druid.util.JdbcUtils;
import junit.framework.TestCase;
public class CobarTest extends TestCase {
private String jdbcUrl;
private String user;
private String password;
private String driverClass;
private DruidDataSource dataSource;
protected void setUp() throws Exception {
jdbcUrl = "jdbc:mysql://10.20.146.88:8066/pt_dragoon_masterdb_test?useUnicode=true&characterEncoding=UTF-8";
user = "pt_dragoon_test";
password = "pt_dragoon_test";
driverClass = "com.mysql.jdbc.Driver";
}
protected void tearDown() throws Exception {
JdbcUtils.close(dataSource);
}
public void test_0() throws Exception {
dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setFilters("stat");
dataSource.setExceptionSorter(MySqlExceptionSorter.class.getName());
Connection conn = dataSource.getConnection();
conn.close();
dataSource.close();
}
}
@@ -0,0 +1,15 @@
package com.alibaba.druid.pool;
import junit.framework.TestCase;
import com.alibaba.druid.pool.ha.config.URLConnectionConfigLoader;
public class URLConfigerLoaderTest extends TestCase {
public void test_0 () throws Exception {
String url = "http://www.baidu.com/";
URLConnectionConfigLoader loader = new URLConnectionConfigLoader(url);
loader.load();
}
}
@@ -0,0 +1,149 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.pool.benckmark;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.NumberFormat;
import java.util.concurrent.CountDownLatch;
import javax.sql.DataSource;
import junit.framework.TestCase;
import org.apache.commons.dbcp.BasicDataSource;
import com.alibaba.druid.TestUtil;
import com.alibaba.druid.pool.DruidDataSource;
public class Case_Concurrent_50 extends TestCase {
private String jdbcUrl;
private String user;
private String password;
private String driverClass;
private int initialSize = 0;
private int minIdle = 3;
private int maxIdle = 5;
private int maxActive = 10;
private String validationQuery = "SELECT 1";
private boolean testOnBorrow = false;
private long minEvictableIdleTimeMillis = 3000;
public final int LOOP_COUNT = 5;
public final int COUNT = 1000 * 10;
private final int THREAD_COUNT = 50;
protected void setUp() throws Exception {
jdbcUrl = "jdbc:fake:dragoon_v25masterdb";
user = "dragoon25";
password = "dragoon25";
driverClass = "com.alibaba.druid.mock.MockDriver";
}
public void test_0() throws Exception {
final DruidDataSource dataSource = new DruidDataSource();
dataSource.setInitialSize(initialSize);
dataSource.setMaxActive(maxActive);
dataSource.setMinIdle(minIdle);
dataSource.setMaxIdle(maxIdle);
dataSource.setPoolPreparedStatements(true);
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(jdbcUrl);
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxWait(6000);
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setValidationQuery(validationQuery);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
for (int i = 0; i < LOOP_COUNT; ++i) {
p0(dataSource, "druid");
}
System.out.println();
}
public void test_1() throws Exception {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setInitialSize(initialSize);
dataSource.setMaxActive(maxActive);
dataSource.setMinIdle(minIdle);
dataSource.setMaxIdle(maxIdle);
dataSource.setPoolPreparedStatements(true);
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(jdbcUrl);
dataSource.setPoolPreparedStatements(true);
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setValidationQuery(validationQuery);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
for (int i = 0; i < LOOP_COUNT; ++i) {
p0(dataSource, "dbcp");
}
System.out.println();
}
private void p0(final DataSource dataSource, String name) throws Exception {
long startMillis = System.currentTimeMillis();
long startYGC = TestUtil.getYoungGC();
long startFullGC = TestUtil.getFullGC();
final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; ++i) {
Thread thread = new Thread() {
public void run() {
try {
for (int i = 0; i < COUNT; ++i) {
Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1");
Thread.sleep(0, 1000 * 100);
rs.close();
stmt.close();
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
endLatch.countDown();
}
}
};
thread.start();
}
endLatch.await();
long millis = System.currentTimeMillis() - startMillis;
long ygc = TestUtil.getYoungGC() - startYGC;
long fullGC = TestUtil.getFullGC() - startFullGC;
System.out.println(name + " millis : " + NumberFormat.getInstance().format(millis) + ", YGC " + ygc + " FGC "
+ fullGC);
}
}