永发信息网

Proxool连接池导致 Oracle 会话持续增加,是什么原因

答案:1  悬赏:30  手机版
解决时间 2021-03-25 19:36
Proxool连接池导致 Oracle 会话持续增加,是什么原因
最佳答案
写JDBC connection pool 的注意事项有:
1. 有一个简单的函数从连接池中得到一个 Connection。
2. close 函数必须将connection 放回 数据库连接池。
3. 当数据库连接池中没有空闲的connection,数据库连接池必须能够自动增加connection 个数。
4. 当数据库连接池中的connection 个数在某一个特别的时间变得很大,但是以后很长时间只用其中一小部分,应该可以自动将多余的connection 关闭掉。
5. 如果可能,应该提供debug 信息报告没有关闭的new Connection 。
如果要new Connection 就可以直接从数据库连接池中返回Connection, 可以这样写( Mediator pattern ) (以下代码中使用了中文全角空格):
public class EasyConnection implements java.sql.Connection{
private Connection m_delegate = null;
public EasyConnection(){
m_delegate = getConnectionFromPool();
}
 public void close(){
putConnectionBackToPool(m_delegate);
}
public PreparedStatement prepareStatement(String sql) throws SQLException{
m_delegate.prepareStatement(sql);
}
//...... other method
}
看来并不难。不过不建议这种写法,因为应该尽量避免使用Java Interface, 关于Java Interface 的缺点我另外再写文章讨论。大家关注的是Connection Pool 的实现方法。下面给出一种实现方法。
import java.sql.*;
import java.lang.reflect.*;
import java.util.*;
import java.io.*;

public class SimpleConnetionPool {
private static LinkedList m_notUsedConnection = new LinkedList();
private static HashSet m_usedUsedConnection = new HashSet();
private static String m_url = "";
private static String m_user = "";
private static String m_password = "";
static final boolean DEBUG = true;
static private long m_lastClearClosedConnection = System.currentTimeMillis();
public static long CHECK_CLOSED_CONNECTION_TIME = 4 * 60 * 60 * 1000; //4 hours

static {
initDriver();
}

private SimpleConnetionPool() {
}

private static void initDriver() {
Driver driver = null;
//load mysql driver
try {
driver = (Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();
installDriver(driver);
} catch (Exception e) {
}

//load postgresql driver
try {
driver = (Driver) Class.forName("org.postgresql.Driver").newInstance();
installDriver(driver);
} catch (Exception e) {
}
}

public static void installDriver(Driver driver) {
try {
DriverManager.registerDriver(driver);
} catch (Exception e) {
e.printStackTrace();
}
}

public static synchronized Connection getConnection() {
clearClosedConnection();
while (m_notUsedConnection.size() > 0) {
try {
ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();
if (wrapper.connection.isClosed()) {
continue;
}
m_usedUsedConnection.add(wrapper);
if (DEBUG) {
wrapper.debugInfo = new Throwable("Connection initial statement");
}
return wrapper.connection;
} catch (Exception e) {
}
}
int newCount = getIncreasingConnectionCount();
LinkedList list = new LinkedList();
ConnectionWrapper wrapper = null;
for (int i = 0; i < newCount; i++) {
wrapper = getNewConnection();
if (wrapper != null) {
list.add(wrapper);
}
}
if (list.size() == 0) {
return null;
}
wrapper = (ConnectionWrapper) list.removeFirst();
m_usedUsedConnection.add(wrapper);

m_notUsedConnection.addAll(list);
list.clear();

return wrapper.connection;
}

private static ConnectionWrapper getNewConnection() {
try {
Connection con = DriverManager.getConnection(m_url, m_user, m_password);
ConnectionWrapper wrapper = new ConnectionWrapper(con);
return wrapper;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

static synchronized void pushConnectionBackToPool(ConnectionWrapper con) {
boolean exist = m_usedUsedConnection.remove(con);
if (exist) {
m_notUsedConnection.addLast(con);
}
}

public static int close() {
int count = 0;

Iterator iterator = m_notUsedConnection.iterator();
while (iterator.hasNext()) {
try {
( (ConnectionWrapper) iterator.next()).close();
count++;
} catch (Exception e) {
}
}
m_notUsedConnection.clear();

iterator = m_usedUsedConnection.iterator();
while (iterator.hasNext()) {
try {
ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();
wrapper.close();
if (DEBUG) {
wrapper.debugInfo.printStackTrace();
}
count++;
} catch (Exception e) {
}
}
m_usedUsedConnection.clear();

return count;
}

private static void clearClosedConnection() {
long time = System.currentTimeMillis();
//sometimes user change system time,just return
if (time < m_lastClearClosedConnection) {
time = m_lastClearClosedConnection;
return;
}
//no need check very often
if (time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME) {
return;
}
m_lastClearClosedConnection = time;

//begin check
Iterator iterator = m_notUsedConnection.iterator();
while (iterator.hasNext()) {
ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();
try {
if (wrapper.connection.isClosed()) {
iterator.remove();
}
} catch (Exception e) {
iterator.remove();
if (DEBUG) {
System.out.println("connection is closed, this connection initial StackTrace");
wrapper.debugInfo.printStackTrace();
}
}
}

//make connection pool size smaller if too big
int decrease = getDecreasingConnectionCount();
if (m_notUsedConnection.size() < decrease) {
return;
}

while (decrease-- > 0) {
ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();
try {
wrapper.connection.close();
} catch (Exception e) {
}
}
}

public static int getIncreasingConnectionCount() {
int count = 1;
int current = getConnectionCount();
count = current / 4;
if (count < 1) {
count = 1;
}
return count;
}

public static int getDecreasingConnectionCount() {
int count = 0;
int current = getConnectionCount();
if (current < 10) {
return 0;
}
return current / 3;
}

public synchronized static void printDebugMsg() {
printDebugMsg(System.out);
}

public synchronized static void printDebugMsg(PrintStream out) {
if (DEBUG == false) {
return;
}
StringBuffer msg = new StringBuffer();
msg.append("debug message in " + SimpleConnetionPool.class.getName());
msg.append("\r\n");
msg.append("total count is connection pool: " + getConnectionCount());
msg.append("\r\n");
msg.append("not used connection count: " + getNotUsedConnectionCount());
msg.append("\r\n");
msg.append("used connection, count: " + getUsedConnectionCount());
out.println(msg);
Iterator iterator = m_usedUsedConnection.iterator();
while (iterator.hasNext()) {
ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();
wrapper.debugInfo.printStackTrace(out);
}
out.println();
}

public static synchronized int getNotUsedConnectionCount() {
return m_notUsedConnection.size();
}

public static synchronized int getUsedConnectionCount() {
return m_usedUsedConnection.size();
}

public static synchronized int getConnectionCount() {
return m_notUsedConnection.size() + m_usedUsedConnection.size();
}

public static String getUrl() {
return m_url;
}

public static void setUrl(String url) {
if (url == null) {
return;
}
m_url = url.trim();
}

public static String getUser() {
return m_user;
}

public static void setUser(String user) {
if (user == null) {
return;
}
m_user = user.trim();
}

public static String getPassword() {
return m_password;
}

public static void setPassword(String password) {
if (password == null) {
return;
}
m_password = password.trim();
}

}

class ConnectionWrapper implements InvocationHandler {
private final static String CLOSE_METHOD_NAME = "close";
public Connection connection = null;
private Connection m_originConnection = null;
public long lastAccessTime = System.currentTimeMillis();
Throwable debugInfo = new Throwable("Connection initial statement");

ConnectionWrapper(Connection con) {
this.connection = (Connection) Proxy.newProxyInstance(
con.getClass().getClassLoader(),
new Class[]{Connection.class}, this);
m_originConnection = con;
}

void close() throws SQLException {
m_originConnection.close();
}

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object obj = null;
if (CLOSE_METHOD_NAME.equals(m.getName())) {
SimpleConnetionPool.pushConnectionBackToPool(this);
}
else {
obj = m.invoke(m_originConnection, args);
}
lastAccessTime = System.currentTimeMillis();
return obj;
}
}
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
烧饼的饼字怎么写
哪种品牌的衣服适合23岁左右女孩穿
你讨厌一个小组一起做zuo ye ma&
北平无战事引用的古文有哪些
东风风行景逸x5胎压多少正常?
outlook2013 提示邮箱快满了 怎么把邮件保存
老婆是平谷城镇户口我是河北兴隆县农村户口想
cpu电源功率64瓦等于多少w
求教轮胎缝隙中的小石子 如何清除~~
今年纹绣很流行啊,有没有免费教纹绣的机构那
溪水 李汉荣
1月中旬 在西安住一天 想住在西安交大西门或
捷克留学生说中国年轻人非常努力吗?
昆山新客站有从昆山到浙江平湖的车么?
1993年办的房产证,当时的姓名也搞错了,不知
推荐资讯
搜集祖国的传统文化
看图猜成语18答案及图片大全
三言两语道不清打一数字
百度 360 搜狗做网络付费点击推广 为啥只有点
某小组测量小艳同学的胸围差时,记录的数据如
刨花板废料可以做成炭吗
Use by JUN 2019是什么意思
鼻梁正中间长颗棕褐色小痣 ,还有眉头正中间的
有人需要瘦身嘛?
请教工业硼酰化钴中钴含量的测试方法?
赵州的历史记载
工业模型的产品种类
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?