mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
DruidDataSource support killWhenSocketReadTimeout
This commit is contained in:
@@ -44,7 +44,7 @@ public final class DruidConnectionHolder {
|
||||
|
||||
private final static Log LOG = LogFactory.getLog(DruidConnectionHolder.class);
|
||||
|
||||
private final DruidAbstractDataSource dataSource;
|
||||
protected final DruidAbstractDataSource dataSource;
|
||||
private final long connectionId;
|
||||
private final Connection conn;
|
||||
private final List<ConnectionEventListener> connectionEventListeners = new CopyOnWriteArrayList<ConnectionEventListener>();
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -173,6 +172,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
|
||||
private volatile boolean keepAlive = false;
|
||||
|
||||
protected boolean killWhenSocketReadTimeout = false;
|
||||
|
||||
public DruidDataSource(){
|
||||
this(false);
|
||||
}
|
||||
@@ -387,6 +388,20 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
Boolean value = getBoolean(properties, "druid.killWhenSocketReadTimeout");
|
||||
if (value != null) {
|
||||
setKillWhenSocketReadTimeout(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isKillWhenSocketReadTimeout() {
|
||||
return killWhenSocketReadTimeout;
|
||||
}
|
||||
|
||||
public void setKillWhenSocketReadTimeout(boolean killWhenSocketTimeOut) {
|
||||
this.killWhenSocketReadTimeout = killWhenSocketTimeOut;
|
||||
}
|
||||
|
||||
public boolean isUseGlobalDataSourceStat() {
|
||||
|
||||
@@ -17,7 +17,11 @@ package com.alibaba.druid.pool;
|
||||
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import com.alibaba.druid.util.MySqlUtils;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -61,10 +65,83 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
}
|
||||
|
||||
protected SQLException checkException(Throwable error) throws SQLException {
|
||||
handleScoketTimeout(error);
|
||||
|
||||
exceptionCount++;
|
||||
return conn.handleException(error);
|
||||
}
|
||||
|
||||
private void handleScoketTimeout(Throwable error) throws SQLException {
|
||||
if (this.conn == null
|
||||
|| this.conn.transactionInfo != null
|
||||
|| this.conn.holder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DruidDataSource dataSource = null;
|
||||
|
||||
if (this.conn.holder.dataSource instanceof DruidDataSource) {
|
||||
dataSource = (DruidDataSource) this.conn.holder.dataSource;
|
||||
}
|
||||
if (dataSource == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dataSource.killWhenSocketReadTimeout) {
|
||||
return;
|
||||
}
|
||||
|
||||
SQLException sqlException = null;
|
||||
if (error instanceof SQLException) {
|
||||
sqlException = (SQLException) error;
|
||||
}
|
||||
|
||||
if (sqlException == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Throwable cause = error.getCause();
|
||||
boolean socketReadTimeout = cause instanceof SocketTimeoutException
|
||||
&& "Read timed out".equals(cause.getMessage());
|
||||
if (!socketReadTimeout) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!JdbcConstants.MYSQL.equals(dataSource.dbType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String killQuery = MySqlUtils.buildKillQuerySql(this.conn.getConnection(), (SQLException) error);
|
||||
|
||||
if (killQuery == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DruidPooledConnection killQueryConn = null;
|
||||
Statement killQueryStmt = null;
|
||||
|
||||
|
||||
try {
|
||||
killQueryConn = dataSource.getConnection(1000);
|
||||
if (killQueryConn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
killQueryStmt = killQueryConn.createStatement();
|
||||
killQueryStmt.execute(killQuery);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(killQuery + " success.");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.warn(killQuery + " error.", ex);
|
||||
} finally {
|
||||
JdbcUtils.close(killQueryStmt);
|
||||
JdbcUtils.close(killQueryConn);
|
||||
}
|
||||
}
|
||||
|
||||
public DruidPooledConnection getPoolableConnection() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,14 @@
|
||||
*/
|
||||
package com.alibaba.druid.util;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.mysql.jdbc.ConnectionImpl;
|
||||
import com.mysql.jdbc.MySQLConnection;
|
||||
import com.mysql.jdbc.MysqlIO;
|
||||
|
||||
import javax.sql.XAConnection;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
@@ -87,4 +93,15 @@ public class MySqlUtils {
|
||||
|
||||
throw new SQLFeatureNotSupportedException();
|
||||
}
|
||||
|
||||
public static String buildKillQuerySql(Connection connection, SQLException error) throws SQLException {
|
||||
try {
|
||||
ConnectionImpl connImpl = (ConnectionImpl) connection;
|
||||
long threadId = connImpl.getId();
|
||||
return "KILL QUERY " + threadId;
|
||||
} catch (Exception e) {
|
||||
// skip
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.alibaba.druid.pool;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 13/06/2017.
|
||||
*/
|
||||
public class ExceptionSorterKillTest {
|
||||
}
|
||||
Reference in New Issue
Block a user