Linux系统中使用druid连接池获取db2和oracle数据库连接缓慢

italy 发布于 2016/04/06 14:26
阅读 737
收藏 0

@wenshao 你好,想跟你请教个问题:

能够正常获取数据库连接的环境为:Windows 8.0 + jdk 1.6 + tomcat 6.0 + druid 1.0.7+quartz 1.8.6

出问题的软件运行环境为:Linux redhat 6.4 + jdk 1.7 + tomcat 7.0.64+druid 1.0.7+quartz 1.8.6

软件的数据源情况:使用的是多数据源,各个数据源的数据库连接URL及druid的配置存储在数据库中,在项目启动时通过监听器查询出所有的数据源并进行加载。

问题描述:在使用quartz定时任务执行数据的修复功能时,在Linux系统中执行到从druid连接池中获取db2数据库连接时,就会卡住。卡住的代码为
Connection conn = poll.getConnection();

poll的声明语句为:DynamicDataSourcePool poll = dataSourceFactory.getDynamicDataSourcePool((String)CacheUtils.get(key.toString()));

每次执行到 poll.getConnection()都要差不多30分钟才能获取到Connection对象。但是在Windows执行却不会出现这样的问题。希望大神能帮助排查下问题的原因在哪儿?

下面是具体的代码,希望有助于排查。

druid数据连接池是通过自己编写的Java代码完成加载的,代码如下:

//初始化数据源
private void initDataSource(){
logger.info("加载数据源 start");

//初始化DynamicDataSourcePoolFactory
DynamicDataSourcePoolFactory dataSourceFactory = DynamicDataSourcePoolFactory.getInstance();
InetAddress addr;
String ip = "";
try {
addr = InetAddress.getLocalHost();
ip = addr.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}

//FIXME 测试用,生产多服务器时去掉
DatasourceCfg cfg = new DatasourceCfg();
cfg.setIp(ip);
datasourceCfgMapper.updateByPrimaryKeySelective(cfg);

//根据IP从数据库中查询出要加载的数据源实例列表
List<DatasourceCfg> cfgs = datasourceCfgMapper.findAllList(ip);
String passKey = "00";
for(DatasourceCfg dc : cfgs){
String key = dc.getDatasourceName();
DynamicDataSourcePool poll = new DynamicDataSourcePool(dc,passKey);
dataSourceFactory.bind(key, poll);//绑定连接池,将poll放到key为键值的HashTable中
String systemSource = dc.getSystemSource();
String module = dc.getModule();
String compidAll = dc.getComids();
String [] compids = compidAll.split(",");
for(String compid : compids){
StringBuffer dataSourceKey = new StringBuffer(systemSource);
if(null != module){
dataSourceKey.append("_"+module);
dataSourceKey.append("_"+compid);
}else{
dataSourceKey.append("_"+key);
}
CacheUtils.put(dataSourceKey.toString(), key);
}
}
logger.info("加载数据源 end");
}


DynamicDataSourcePool的构造方法:

public DynamicDataSourcePool(DatasourceCfg dc,String datakey) {
String password = "";
try {
EncryptUtil eu = new EncryptUtil(datakey);
password = eu.decrypt(dc.getPass());
} catch (Exception e) {
e.printStackTrace();
}
String url = dc.getJdbcUrl();
try {
dataSource.setDriverClassName(dc.getDriverClass());// 设置驱动
dataSource.setUrl(url); // 设置连接的url
dataSource.setUsername(dc.getUserName());// 设置数据库用户名
dataSource.setPassword(password);// 设置数据库密码
dataSource.setInitialSize(dc.getInitialPoolSize());//dc.getInitialPoolSize()=1
dataSource.setMinIdle(dc.getMinPoolSize());//dc.getMinPoolSize()=1
dataSource.setMaxActive(dc.getMaxPoolSize());//dc.getMaxPoolSize()=500
dataSource.setMaxWait(60000);
dataSource.setTimeBetweenEvictionRunsMillis(60000);
dataSource.setMinEvictableIdleTimeMillis(300000);
//检测是否有未释放的连接
//dataSource.setRemoveAbandoned(true);
//dataSource.setRemoveAbandonedTimeout(1800);
//dataSource.setLogAbandoned(true);

//打开PSCache,并且指定每个连接上PSCache的大小。
//mysql不需要做PSCache,只有Oracle/DB2/SQL Server之类支持游标的数据库才需要这样配置。所以设置为false。
String testSql = "SELECT 'x' FROM DUAL";
if(dc.getDriverClass().equals("com.ibm.db2.jcc.DB2Driver")){
testSql = "SELECT 1 FROM sysibm.sysdummy1";
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
}else if(dc.getDriverClass().equals("oracle.jdbc.driver.OracleDriver")){
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
}else{
dataSource.setPoolPreparedStatements(false);
}
dataSource.setValidationQuery(testSql);
dataSource.setTestWhileIdle(true);
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setFilters("stat");

logger.info(url+":数据库连接池初始化成功!");
} catch (SQLException e) {
e.printStackTrace();
}
}


以上为初始化数据源的相关代码。下面是出现问题的定时任务的相关代码。经排查,定时任务执行到下面语句时卡住:Connection conn = DateSourceManager.getConnection(SystemConstant.SYSTEM_EAS,Global.getConfig("eas.datasource"),logger);

DateSourceManager.getConnection的方法实现为:

/**
* 获取动态链接池
* @param system 系统来源
* @param dataSourceName 数据源名称
* @return
*/
public static Connection getConnection(String system,String dataSourceName,Logger logger){
if(SystemConstant.SYSTEM_TAX.equals(system)){
//return getConnection(system, dataSourceName);
}
logger.info("开始获取连接。。。。。。");
long a=System.currentTimeMillis();
DynamicDataSourcePoolFactory dataSourceFactory = DynamicDataSourcePoolFactory.getInstance();
String key = CacheUtils.get(system+"_"+dataSourceName).toString();
logger.info("key = :"+ key);
DynamicDataSourcePool poll = dataSourceFactory.getDynamicDataSourcePool(key);//从HashTable中取出与key相对应的DynamicDataSourcePool实例。
logger.info("获取连接池完成。。。。pool dump : "+ poll.dump());
Connection conn = poll.getConnection();//经排查,定时任务执行时卡在此处!!!
logger.info("CONNECTION :URL="+poll.getJdbcUrl()+":获取连接耗时"+(System.currentTimeMillis()-a)/1000f+" 秒 ");
return conn;
}

poll.getConnection()的方法实现为:

/**
* 得到连接

* @return
*/
public Connection getConnection() {
try {
return this.dataSource.getConnection();//DruidDataSource dataSource = new DruidDataSource();创建对象。最后追踪到此处,要等30分钟才能返回Connection对象。
} catch (SQLException e) {
logger.info("获取连接异常");
e.printStackTrace();
}
return null;
}

加载中
0
小鸣扬

试试在/etc/hosts下加上 本机ip和hostname的映射 

如:

192.168.0.1 192.168.0.1 appserver

返回顶部
顶部