当前位置: 技术问答>java相关
讨论下数据库连接池的东东如何?(JSP+JavaBean+Oracle)有赏!
来源: 互联网 发布时间:2015-10-15
本文导语: 高分请教下各位高手. 现在正做着一个WEB的应用程序,JSP+JavaBean+Oracle,连接DB及逻辑处理均在BEAN的部分处理.因为访问量比较大,设想同时在线用户达到1000以上,DB的数据量达50万以上,如何用池化的连接进行性能的提高?各位...
高分请教下各位高手.
现在正做着一个WEB的应用程序,JSP+JavaBean+Oracle,连接DB及逻辑处理均在BEAN的部分处理.因为访问量比较大,设想同时在线用户达到1000以上,DB的数据量达50万以上,如何用池化的连接进行性能的提高?各位分享下这方面的经验如何?
我试过使用一个网上找到的连接池的管理的东东,但那是在Servlet上用,我把她稍修改使用在JSP+BEAN上好似没有达到预期的效果.诚心请教各位.sourcecode better.
现在正做着一个WEB的应用程序,JSP+JavaBean+Oracle,连接DB及逻辑处理均在BEAN的部分处理.因为访问量比较大,设想同时在线用户达到1000以上,DB的数据量达50万以上,如何用池化的连接进行性能的提高?各位分享下这方面的经验如何?
我试过使用一个网上找到的连接池的管理的东东,但那是在Servlet上用,我把她稍修改使用在JSP+BEAN上好似没有达到预期的效果.诚心请教各位.sourcecode better.
|
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
/**
* 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接
* 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.
*/
public class DBConnectionManager {
static private DBConnectionManager instance; // 唯一实例
static private int clients;
private Vector drivers = new Vector();
private PrintWriter log;
private Hashtable pools = new Hashtable();
/**
* 返回唯一实例.如果是第一次调用此方法,则创建实例
*
* @return DBConnectionManager 唯一实例
*/
static synchronized public DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager();
}
clients++;
return instance;
}
/**
* 建构函数私有以防止其它对象创建本类实例
*/
private DBConnectionManager() {
init();
}
/**
* 将连接对象返回给由名字指定的连接池
*
* @param name 在属性文件中定义的连接池名字
* @param con 连接对象
*/
public void freeConnection(String name, Connection con) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
pool.freeConnection(con);
}
}
/**
* 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数
* 限制,则创建并返回新连接
*
* @param name 在属性文件中定义的连接池名字
* @return Connection 可用连接或null
*/
public Connection getConnection(String name) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection();
}
return null;
}
/**
* 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,
* 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
*
* @param name 连接池名字
* @param time 以毫秒计的等待时间
* @return Connection 可用连接或null
*/
public Connection getConnection(String name, long time) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection(time);
}
return null;
}
/**
* 关闭所有连接,撤销驱动程序的注册
*/
public synchronized void release() {
// 等待直到最后一个客户程序调用
if (--clients != 0) {
return;
}
Enumeration allPools = pools.elements();
while (allPools.hasMoreElements()) {
DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
pool.release();
}
Enumeration allDrivers = drivers.elements();
while (allDrivers.hasMoreElements()) {
Driver driver = (Driver) allDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");
}
catch (SQLException e) {
log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
}
}
}
/**
* 根据指定属性创建连接池实例.
*
* @param props 连接池属性
*/
private void createPools(Properties props) {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
String name = (String) propNames.nextElement();
if (name.endsWith(".url")) {
String poolName = name.substring(0, name.lastIndexOf("."));
String url = props.getProperty(poolName + ".url");
if (url == null) {
log("没有为连接池" + poolName + "指定URL");
continue;
}
String user = props.getProperty(poolName + ".user");
String password = props.getProperty(poolName + ".password");
String maxconn = props.getProperty(poolName + ".maxconn", "0");
int max;
try {
max = Integer.valueOf(maxconn).intValue();
}
catch (NumberFormatException e) {
log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);
max = 0;
}
DBConnectionPool pool =new DBConnectionPool(poolName, url, user, password, max);
pools.put(poolName, pool);
log("成功创建连接池" + poolName);
}
}
}
/**
* 读取属性完成初始化
*/
private void init() {
InputStream is = getClass().getResourceAsStream("/db.properties");
Properties dbProps = new Properties();
try {
dbProps.load(is);
}
catch (Exception e) {
System.err.println("不能读取属性文件. " +
"请确保db.properties在CLASSPATH指定的路径中");
return;
}
String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log");
try {
log = new PrintWriter(new FileWriter(logFile, true), true);
}
catch (IOException e) {
System.err.println("无法打开日志文件: " + logFile);
log = new PrintWriter(System.err);
}
loadDrivers(dbProps);
createPools(dbProps);
}
/**
* 装载和注册所有JDBC驱动程序
*
* @param props 属性
*/
private void loadDrivers(Properties props) {
String driverClasses = props.getProperty("drivers");
StringTokenizer st = new StringTokenizer(driverClasses);
while (st.hasMoreElements()) {
String driverClassName = st.nextToken().trim();
try {
Driver driver = (Driver)Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
drivers.addElement(driver);
log("成功注册JDBC驱动程序" + driverClassName);
}
catch (Exception e) {
log("无法注册JDBC驱动程序: " +
driverClassName + ", 错误: " + e);
}
}
}
/**
* 将文本信息写入日志文件
*/
private void log(String msg) {
log.println(new Date() + ": " + msg);
}
/**
* 将文本信息与异常写入日志文件
*/
private void log(Throwable e, String msg) {
log.println(new Date() + ": " + msg);
e.printStackTrace(log);
}
import java.sql.*;
import java.util.*;
import java.util.Date;
/**
* 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接
* 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.
*/
public class DBConnectionManager {
static private DBConnectionManager instance; // 唯一实例
static private int clients;
private Vector drivers = new Vector();
private PrintWriter log;
private Hashtable pools = new Hashtable();
/**
* 返回唯一实例.如果是第一次调用此方法,则创建实例
*
* @return DBConnectionManager 唯一实例
*/
static synchronized public DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager();
}
clients++;
return instance;
}
/**
* 建构函数私有以防止其它对象创建本类实例
*/
private DBConnectionManager() {
init();
}
/**
* 将连接对象返回给由名字指定的连接池
*
* @param name 在属性文件中定义的连接池名字
* @param con 连接对象
*/
public void freeConnection(String name, Connection con) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
pool.freeConnection(con);
}
}
/**
* 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数
* 限制,则创建并返回新连接
*
* @param name 在属性文件中定义的连接池名字
* @return Connection 可用连接或null
*/
public Connection getConnection(String name) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection();
}
return null;
}
/**
* 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,
* 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
*
* @param name 连接池名字
* @param time 以毫秒计的等待时间
* @return Connection 可用连接或null
*/
public Connection getConnection(String name, long time) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection(time);
}
return null;
}
/**
* 关闭所有连接,撤销驱动程序的注册
*/
public synchronized void release() {
// 等待直到最后一个客户程序调用
if (--clients != 0) {
return;
}
Enumeration allPools = pools.elements();
while (allPools.hasMoreElements()) {
DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
pool.release();
}
Enumeration allDrivers = drivers.elements();
while (allDrivers.hasMoreElements()) {
Driver driver = (Driver) allDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");
}
catch (SQLException e) {
log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
}
}
}
/**
* 根据指定属性创建连接池实例.
*
* @param props 连接池属性
*/
private void createPools(Properties props) {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
String name = (String) propNames.nextElement();
if (name.endsWith(".url")) {
String poolName = name.substring(0, name.lastIndexOf("."));
String url = props.getProperty(poolName + ".url");
if (url == null) {
log("没有为连接池" + poolName + "指定URL");
continue;
}
String user = props.getProperty(poolName + ".user");
String password = props.getProperty(poolName + ".password");
String maxconn = props.getProperty(poolName + ".maxconn", "0");
int max;
try {
max = Integer.valueOf(maxconn).intValue();
}
catch (NumberFormatException e) {
log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);
max = 0;
}
DBConnectionPool pool =new DBConnectionPool(poolName, url, user, password, max);
pools.put(poolName, pool);
log("成功创建连接池" + poolName);
}
}
}
/**
* 读取属性完成初始化
*/
private void init() {
InputStream is = getClass().getResourceAsStream("/db.properties");
Properties dbProps = new Properties();
try {
dbProps.load(is);
}
catch (Exception e) {
System.err.println("不能读取属性文件. " +
"请确保db.properties在CLASSPATH指定的路径中");
return;
}
String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log");
try {
log = new PrintWriter(new FileWriter(logFile, true), true);
}
catch (IOException e) {
System.err.println("无法打开日志文件: " + logFile);
log = new PrintWriter(System.err);
}
loadDrivers(dbProps);
createPools(dbProps);
}
/**
* 装载和注册所有JDBC驱动程序
*
* @param props 属性
*/
private void loadDrivers(Properties props) {
String driverClasses = props.getProperty("drivers");
StringTokenizer st = new StringTokenizer(driverClasses);
while (st.hasMoreElements()) {
String driverClassName = st.nextToken().trim();
try {
Driver driver = (Driver)Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
drivers.addElement(driver);
log("成功注册JDBC驱动程序" + driverClassName);
}
catch (Exception e) {
log("无法注册JDBC驱动程序: " +
driverClassName + ", 错误: " + e);
}
}
}
/**
* 将文本信息写入日志文件
*/
private void log(String msg) {
log.println(new Date() + ": " + msg);
}
/**
* 将文本信息与异常写入日志文件
*/
private void log(Throwable e, String msg) {
log.println(new Date() + ": " + msg);
e.printStackTrace(log);
}
|
你应该在第一次使用的时候就建立这个连接池,以后只从里面取一个连接就可以了,退出的时候关闭这个连接池(根据static private int clients这个来判断是否为最后一个客户程序调用,如果是就关闭)。
我在用DBConnectionManager时加了下面一个方法,作用是得到这个连接池,但并不为这个连接池的客户数加一,这样总是保持同一时间只会建立一次连接池。在用户退出时才关闭连接池。
static synchronized public DBConnectionManager getConnectionPool()
{
if(instance == null)
{
instance = getInstance();
}
return instance;
}
我在用DBConnectionManager时加了下面一个方法,作用是得到这个连接池,但并不为这个连接池的客户数加一,这样总是保持同一时间只会建立一次连接池。在用户退出时才关闭连接池。
static synchronized public DBConnectionManager getConnectionPool()
{
if(instance == null)
{
instance = getInstance();
}
return instance;
}
|
告诉我你的邮箱,我给你发一份程序
它是用xml来做配置文件的
已经在一个网站项目中用过了,非常好用
它是用xml来做配置文件的
已经在一个网站项目中用过了,非常好用
|
用tomcat可以配置连接池,在server.xml中有例子:
如:
usermyuser
passwordmypasswd
driverClassName
oracle.jdbc.driver.OracleDriver
driverName
jdbc:oracle:thin:@mydbserver:1521:mydbsid
我在用jdbc-odbc桥方式时也出数据库错误,用了一段时间就报连接错误;
用thin方式后没出过该毛病,
tomcat版本4.0.1
如:
usermyuser
passwordmypasswd
driverClassName
oracle.jdbc.driver.OracleDriver
driverName
jdbc:oracle:thin:@mydbserver:1521:mydbsid
我在用jdbc-odbc桥方式时也出数据库错误,用了一段时间就报连接错误;
用thin方式后没出过该毛病,
tomcat版本4.0.1
|
poolman不仅可以是数据库连接池,也可以做其他资源的缓冲池。
多看看它的文档,会对数据库连接池有跟进一步的了解。
对于大数据量测试,连接池就死掉,应该使用orion做服务器,监控数据连接释放情况。等真正体会了连接的创建和释放后再转为tomcat或其他。
tomcat4里面多了tyrex-0.9.7.0.jar,如果看看官方文档,就会发现在tomcat3.X时,这是个第三方的数据库连接池包。所以,建议使用现有的比较成熟的数据库连接池产品。不反对好学者自己研究研究。
多看看它的文档,会对数据库连接池有跟进一步的了解。
对于大数据量测试,连接池就死掉,应该使用orion做服务器,监控数据连接释放情况。等真正体会了连接的创建和释放后再转为tomcat或其他。
tomcat4里面多了tyrex-0.9.7.0.jar,如果看看官方文档,就会发现在tomcat3.X时,这是个第三方的数据库连接池包。所以,建议使用现有的比较成熟的数据库连接池产品。不反对好学者自己研究研究。
|
http://jakarta.apache.org/tomcat/tomcat-4.0-doc/jndi-resources-howto.html
|
直接用J2EE ApplicationServer上的DataSource不就完了吗,要省钱那就用JDBC2.0可选包里的DataSource,下载数据库驱动,比如Oracle的JDBC驱动就有DataSource和连接池。
|
对了,我用Tomcat4.03的JNDI连接池的时候,一般访问不会出现错误。但我作
告负载的压力测试的时候,就会出现不知为什么,程序中的con.close()应该是将当前连接归还到连接池呀,不可能手工关闭物理连接的。
告负载的压力测试的时候,就会出现不知为什么,程序中的con.close()应该是将当前连接归还到连接池呀,不可能手工关闭物理连接的。
|
上述方法,已经不合适了,
应该采用jsp/servlet + ejb + dao + Oracle,来设计。
应该采用jsp/servlet + ejb + dao + Oracle,来设计。
|
core servlet and JSP这本书里有一个连接池的例子,也许可以参考一下:
http://archive.coreservlets.com/Chapter18.html
http://archive.coreservlets.com/Chapter18.html
|
to:lbluekey(蓝鸟)
对这个东西con.close()我也有疑问,这样好象是关闭了实际连接,要用类似如datasource.close(con)方式关闭可能才用到连接池。
哪位已经知道的或者有时间的摸索一把给个解释吧
对这个东西con.close()我也有疑问,这样好象是关闭了实际连接,要用类似如datasource.close(con)方式关闭可能才用到连接池。
哪位已经知道的或者有时间的摸索一把给个解释吧
|
我是在servlet里直接import connect.*
代码基本与你写的一致,服务器为apache
数据库也是与webserver分离的,我刚才试着拔掉网线。还好啊。。
代码基本与你写的一致,服务器为apache
数据库也是与webserver分离的,我刚才试着拔掉网线。还好啊。。
|
怎么不用poolman呢??
我觉得是一个不错的连接池
我觉得是一个不错的连接池
|
使用Oracle 的 JDBC 其中有对连接池的支持类!
|
我也是用上面的连接方式,WebServer用的是tomcat3.3.1,但我发现一个问题。就是当我进行多次不停的连接时,连接会出错,然后就再也连接不上了,当重起tomcat之后,又回复了正常。哪位大虾若是知道,请不吝赐教,谢了!
|
con.close()本来就是关闭实际的连接
|
aq.executeQuery: ORA-00020: maximum number of processes (59) exceeded
不看你的代码,就看看你的这个错误信息就很明显——资源、资源,没有释放!
上面是不是ASP或其他语言的写法,不要紧慢慢来,多看书,看好书~!
不看你的代码,就看看你的这个错误信息就很明显——资源、资源,没有释放!
上面是不是ASP或其他语言的写法,不要紧慢慢来,多看书,看好书~!