先说说项目情况吧,公司承建了中国电信14个省公司的号码百事通114查号平台,平台中有一个socket服务程序负责接收座席客户端的查号消息,解析消息,获得查号关键条件,组织sql查询数据库,查询相关信息,并同时记录座席操作日志(座席人员工资结算以日志为准),操作完成后组织消息返回给座席客户端。
socket服务程序是由我搭建的一个socekt框架的一部分功能负责,该框架支持阻塞式的socket通讯,支持长连接和短连接两种方式,多线程并发处理消息收发,数据库操作使用apache开源项目torque,在各省平台中使用时,在一些业务量大的省公司平台上,出现了DBCP数据库连接池无法及时回收连接的情况,造成socket服务程序无法提供服务,为了解决该问题,修改torque源码,实现对C3P0数据库连接池的支持,代码升级后,均未再现上述问题。
torque支持C3P0:
1、下载C3P0:c3p0-0.9.1.2.jar、c3p0-oracle-thin-extras-0.9.1.2.jar
2、继承AbstractDataSourceFactory实现基于C3P0数据库连接池的工厂类,编译后打包新的jar包
3、修改torque.properties,将连接池配置改为C3P0方式
4、将涉及包和配置文件放入工程
C3P0DataSourceFactory.java源码:
torque.properties 配置文件:
[quote]
# -------------------------------------------------------------------
# $Id: Torque.properties,v 1.11.2.2 2004/08/24 04:14:32 seade Exp $
#
# This is the configuration file for Torque.
#
# Note that strings containing "," (comma) characters must backslash
# escape the comma (i.e. '\,')
#
# -------------------------------------------------------------------
torque.applicationRoot = .
# -------------------------------------------------------------------
#
# L O G G I N G
#
# -------------------------------------------------------------------
# We use Log4J for all Torque logging and we embed the log4j
# properties within our application configuration.
# -------------------------------------------------------------------
# This first category is required and the category
# must be named 'default'. This is used for all logging
# where an explicit category is not specified.
log4j.category.org.apache.torque = ALL, org.apache.torque
log4j.appender.org.apache.torque = org.apache.log4j.FileAppender
log4j.appender.org.apache.torque.layout = org.apache.log4j.PatternLayout
log4j.appender.org.apache.torque.layout.conversionPattern = %d [%t] %-5p %c - %m%n
log4j.appender.org.apache.torque.append = false
# -------------------------------------------------------------------
#
# T O R Q U E P R O P E R T I E S
#
# -------------------------------------------------------------------
# These are your database settings. Look in the
# org.apache.torque.pool.* packages for more information.
#
# The parameters to connect to the default database. You MUST
# configure these properly.
# -------------------------------------------------------------------
torque.database.default=ups
torque.database.ups.adapter=oracle
# # Using commons-dbcp
#torque.dsfactory.yf.factory=org.apache.torque.dsfactory.SharedPoolDataSourceFactory
#torque.dsfactory.yf.pool.maxIdle=8
#torque.dsfactory.yf.pool.maxActive=10
#torque.dsfactory.yf.pool.testOnBorrow=true
#torque.dsfactory.yf.pool.validationQuery=select * from dual
#torque.dsfactory.yf.connection.driver = oracle.jdbc.driver.OracleDriver
#torque.dsfactory.yf.connection.url = jdbc:oracle:thin:@10.7.118.55:1521:shup
#torque.dsfactory.yf.connection.user = shup
#torque.dsfactory.yf.connection.password = shup
# # Using c3p0
torque.dsfactory.ups.factory=org.apache.torque.dsfactory.C3P0DataSourceFactory
#<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
torque.dsfactory.ups.pool.acquireIncrement=3
#<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
torque.dsfactory.ups.pool.acquireRetryAttempts=30
#<!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
#torque.dsfactory.ups.pool.acquireRetryDelay=1000
#<!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。
#单位毫秒。Default: 0 -->
torque.dsfactory.ups.pool.checkoutTimeout=30000
#<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
torque.dsfactory.ups.pool.initialPoolSize=3
#<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。
#单位:秒 Default: 0 -->
torque.dsfactory.ups.pool.maxIdleTime=0
#<!--连接池中保留的最大连接数。Default: 15 -->
torque.dsfactory.ups.pool.maxPoolSize=20
#<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
#属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
#如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
torque.dsfactory.ups.pool.maxStatements=150
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
torque.dsfactory.ups.pool.maxStatementsPerConnection=0
#<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能
#通过多线程实现多个操作同时被执行。Default: 3-->
torque.dsfactory.ups.pool.numHelperThreads=3
#<!--每60秒检查所有连接池中的空闲连接。单位:秒 Default: 0 -->
torque.dsfactory.ups.pool.idleConnectionTestPeriod=600
#<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
#测试的表必须在初始数据源的时候就存在。Default: null-->
torque.dsfactory.ups.pool.preferredTestQuery=select * from dual
#ups connnection
torque.dsfactory.ups.connection.driverClass = oracle.jdbc.driver.OracleDriver
torque.dsfactory.ups.connection.jdbcUrl = jdbc:oracle:thin:@10.7.118.55:1521:shup
torque.dsfactory.ups.connection.user = shup
torque.dsfactory.ups.connection.password = shup
# Determines if the quantity column of the IDBroker's id_table should
# be increased automatically if requests for ids reaches a high
# volume.
torque.idbroker.clever.quantity=false
# Determines whether the managers cache instances of the business objects.
# And also whether the MethodResultCache will really cache results.
torque.manager.useCache = true
[/quote]
socket服务程序是由我搭建的一个socekt框架的一部分功能负责,该框架支持阻塞式的socket通讯,支持长连接和短连接两种方式,多线程并发处理消息收发,数据库操作使用apache开源项目torque,在各省平台中使用时,在一些业务量大的省公司平台上,出现了DBCP数据库连接池无法及时回收连接的情况,造成socket服务程序无法提供服务,为了解决该问题,修改torque源码,实现对C3P0数据库连接池的支持,代码升级后,均未再现上述问题。
torque支持C3P0:
1、下载C3P0:c3p0-0.9.1.2.jar、c3p0-oracle-thin-extras-0.9.1.2.jar
2、继承AbstractDataSourceFactory实现基于C3P0数据库连接池的工厂类,编译后打包新的jar包
3、修改torque.properties,将连接池配置改为C3P0方式
4、将涉及包和配置文件放入工程
C3P0DataSourceFactory.java源码:
package org.apache.torque.dsfactory;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import org.apache.commons.configuration.Configuration;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.torque.Torque;
import org.apache.torque.TorqueException;
/**
* A factory that looks up the DataSource using the JDBC2 pool methods.
*
* @author <a href="mailto:jmcnally@apache.org">John McNally</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @version $Id: C3P0DataSourceFactory.java 476550 2006-11-18 16:08:37Z tfischer $
*/
public class C3P0DataSourceFactory
extends AbstractDataSourceFactory
{
/** The log. */
private static Log log
= LogFactory.getLog(C3P0DataSourceFactory.class);
/** The wrapped <code>DataSource</code>. */
private ComboPooledDataSource ds = null;
/**
* @see org.apache.torque.dsfactory.DataSourceFactory#getDataSource
*/
public DataSource getDataSource()
{
return ds;
}
/**
* @see org.apache.torque.dsfactory.DataSourceFactory#initialize
*/
public void initialize(Configuration configuration) throws TorqueException
{
log.debug("Starting initialize ----------- ");
super.initialize(configuration);
ComboPooledDataSource dataSource = initJdbc2Pool(configuration);
this.ds = dataSource;
}
/**
* Initializes the Jdbc2PoolDataSource.
*
* @param configuration where to read the settings from
* @throws TorqueException if a property set fails
* @return a configured <code>Jdbc2PoolDataSource</code>
*/
private ComboPooledDataSource initJdbc2Pool(Configuration configuration)
throws TorqueException
{
log.debug("Starting initJdbc2Pool");
Configuration c = Torque.getConfiguration();
ComboPooledDataSource dataSource = new ComboPooledDataSource();
if (c == null || c.isEmpty())
{
log.warn("Global Configuration not set,"
+ " no Default pool data source configured!");
}
else
{
Configuration conf = c.subset(DEFAULT_POOL_KEY);
applyConfiguration(conf, dataSource);
}
//init 数据库连接
Configuration connConf = configuration.subset(CONNECTION_KEY);
applyConfiguration(connConf, dataSource);
//init 数据库连接池
Configuration conf = configuration.subset(POOL_KEY);
applyConfiguration(conf, dataSource);
return dataSource;
}
/**
* Closes the pool associated with this factory and releases it.
* @throws TorqueException if the pool cannot be closed properly
*/
public void close() throws TorqueException
{
try
{
ds.close();
}
catch (Exception e)
{
log.error("Exception caught during close()", e);
throw new TorqueException(e);
}
ds = null;
}
}
torque.properties 配置文件:
[quote]
# -------------------------------------------------------------------
# $Id: Torque.properties,v 1.11.2.2 2004/08/24 04:14:32 seade Exp $
#
# This is the configuration file for Torque.
#
# Note that strings containing "," (comma) characters must backslash
# escape the comma (i.e. '\,')
#
# -------------------------------------------------------------------
torque.applicationRoot = .
# -------------------------------------------------------------------
#
# L O G G I N G
#
# -------------------------------------------------------------------
# We use Log4J for all Torque logging and we embed the log4j
# properties within our application configuration.
# -------------------------------------------------------------------
# This first category is required and the category
# must be named 'default'. This is used for all logging
# where an explicit category is not specified.
log4j.category.org.apache.torque = ALL, org.apache.torque
log4j.appender.org.apache.torque = org.apache.log4j.FileAppender
log4j.appender.org.apache.torque.layout = org.apache.log4j.PatternLayout
log4j.appender.org.apache.torque.layout.conversionPattern = %d [%t] %-5p %c - %m%n
log4j.appender.org.apache.torque.append = false
# -------------------------------------------------------------------
#
# T O R Q U E P R O P E R T I E S
#
# -------------------------------------------------------------------
# These are your database settings. Look in the
# org.apache.torque.pool.* packages for more information.
#
# The parameters to connect to the default database. You MUST
# configure these properly.
# -------------------------------------------------------------------
torque.database.default=ups
torque.database.ups.adapter=oracle
# # Using commons-dbcp
#torque.dsfactory.yf.factory=org.apache.torque.dsfactory.SharedPoolDataSourceFactory
#torque.dsfactory.yf.pool.maxIdle=8
#torque.dsfactory.yf.pool.maxActive=10
#torque.dsfactory.yf.pool.testOnBorrow=true
#torque.dsfactory.yf.pool.validationQuery=select * from dual
#torque.dsfactory.yf.connection.driver = oracle.jdbc.driver.OracleDriver
#torque.dsfactory.yf.connection.url = jdbc:oracle:thin:@10.7.118.55:1521:shup
#torque.dsfactory.yf.connection.user = shup
#torque.dsfactory.yf.connection.password = shup
# # Using c3p0
torque.dsfactory.ups.factory=org.apache.torque.dsfactory.C3P0DataSourceFactory
#<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
torque.dsfactory.ups.pool.acquireIncrement=3
#<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
torque.dsfactory.ups.pool.acquireRetryAttempts=30
#<!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
#torque.dsfactory.ups.pool.acquireRetryDelay=1000
#<!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。
#单位毫秒。Default: 0 -->
torque.dsfactory.ups.pool.checkoutTimeout=30000
#<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
torque.dsfactory.ups.pool.initialPoolSize=3
#<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。
#单位:秒 Default: 0 -->
torque.dsfactory.ups.pool.maxIdleTime=0
#<!--连接池中保留的最大连接数。Default: 15 -->
torque.dsfactory.ups.pool.maxPoolSize=20
#<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
#属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
#如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
torque.dsfactory.ups.pool.maxStatements=150
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
torque.dsfactory.ups.pool.maxStatementsPerConnection=0
#<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能
#通过多线程实现多个操作同时被执行。Default: 3-->
torque.dsfactory.ups.pool.numHelperThreads=3
#<!--每60秒检查所有连接池中的空闲连接。单位:秒 Default: 0 -->
torque.dsfactory.ups.pool.idleConnectionTestPeriod=600
#<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:
#测试的表必须在初始数据源的时候就存在。Default: null-->
torque.dsfactory.ups.pool.preferredTestQuery=select * from dual
#ups connnection
torque.dsfactory.ups.connection.driverClass = oracle.jdbc.driver.OracleDriver
torque.dsfactory.ups.connection.jdbcUrl = jdbc:oracle:thin:@10.7.118.55:1521:shup
torque.dsfactory.ups.connection.user = shup
torque.dsfactory.ups.connection.password = shup
# Determines if the quantity column of the IDBroker's id_table should
# be increased automatically if requests for ids reaches a high
# volume.
torque.idbroker.clever.quantity=false
# Determines whether the managers cache instances of the business objects.
# And also whether the MethodResultCache will really cache results.
torque.manager.useCache = true
[/quote]