发布时间 : 星期四 文章数据库连接池更新完毕开始阅读
wasCancelled = true;
} catch (SQLException sqlEx) {
throw new RuntimeException(sqlEx.toString()); } finally {
if (cancelStmt != null) { try {
cancelStmt.close();
} catch (SQLException sqlEx) {
throw new RuntimeException(sqlEx.toString()); } }
if (cancelConn != null) { try {
cancelConn.close();
} catch (SQLException sqlEx) {
throw new RuntimeException(sqlEx.toString()); } } } } };
cancelThread.start(); } }
class CancelTask extends TimerTask { long connectionId = 0;
CancelTask() throws SQLException {
connectionId = connection.getIO().getThreadId(); }
public void run() {
Thread cancelThread = new Thread() { public void run() {
Connection cancelConn = null;
java.sql.Statement cancelStmt = null; try {
cancelConn = connection.duplicate();
cancelStmt = cancelConn.createStatement();
// 简单暴力,再发起一条KILL SQL,关闭先前的sql thread id cancelStmt.execute(\wasCancelled = true;
} catch (SQLException sqlEx) {
throw new RuntimeException(sqlEx.toString()); } finally {
if (cancelStmt != null) { try {
cancelStmt.close();
} catch (SQLException sqlEx) {
throw new RuntimeException(sqlEx.toString()); } }
if (cancelConn != null) { try {
cancelConn.close();
} catch (SQLException sqlEx) {
throw new RuntimeException(sqlEx.toString()); } } } } };
cancelThread.start(); } }
原因总结一句话: queryTimeout的实现是通过底层数据库提供的机制,比如KILL QUERY pid. 如果此时的网络不通,出现阻塞现象,对应的kill命令也发不出去,所以timeout设置的超时没效果。 4.最后
最后还是决定配置testWhileIdle扫描,主要考虑:
pool池中的链接如果未被使用,可以通过testWhileIdle进行链接检查,避免在使用时后总要失败那么一次,可以及时预防
配合连接池的minEvictableIdleTimeMillis(空闲链接),removeAbandoned(未释放的链接),可以更好的去避免因为一些异常情况引起的问题,防范于未然。比如使用一些分布式数据库的中间件,会有空闲链接关闭的动作,动态伸缩连接池,这时候需要能及时的发现,避免请求失败。
testOnBorrow个人不太建议使用,存在性能问题,试想一下连接一般会在什么情况出问题,网络或者服务端异常终端空闲链接,网络中断你testOnBorrow检
查发现不对再取一个链接还是不对,针对空闲链接处理异常关闭,可以从好业务端的重试策略进行考虑,同时配置客户端的空闲链接超时时间,maxIdle,minIdle等。
-------------------------------------------- 新加的内容:
5.dbcp密码加密处理
以前使用jboss的jndi数据源的方式,是通过配置oracle-ds.xml,可以设置
Java代码
code=\flag=\ name=\${jndiName}
< application-policy name=\ code=\flag=\ name=\${jndiName}
为了能达到同样的效果,切换为spring dbcp配置时,也有类似密码加密的功能,运行期进行密码decode,最后进行数据链接。
实现方式很简单,分析jboss的对应SecureIdentityLoginModule的实现,无非就是走了Blowfish加密算法,自己拷贝实现一份。
Java代码
private static String encode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] kbytes = \
SecretKeySpec key = new SecretKeySpec(kbytes, \
Cipher cipher = Cipher.getInstance(\cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encoding = cipher.doFinal(secret.getBytes()); BigInteger n = new BigInteger(encoding); return n.toString(16); }
private static char[] decode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] kbytes = \
SecretKeySpec key = new SecretKeySpec(kbytes, \
BigInteger n = new BigInteger(secret, 16); byte[] encoding = n.toByteArray();
Cipher cipher = Cipher.getInstance(\cipher.init(Cipher.DECRYPT_MODE, key); byte[] decode = cipher.doFinal(encoding); return new String(decode).toCharArray(); }
private static String encode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] kbytes = \
SecretKeySpec key = new SecretKeySpec(kbytes, \Cipher cipher = Cipher.getInstance(\cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encoding = cipher.doFinal(secret.getBytes()); BigInteger n = new BigInteger(encoding);