另类解决c3p0连接池获取连接时候长时间阻塞线程问题
2017-03-20 21:08
423 查看
一直维护着旧游戏服务器 java写的,一台服务器还有3,4千人在线,看来老外还蛮怀旧的。
服务器出现无法登录时候,在服务器JDB 记录下多线程调用堆栈记录 以下是出现次数最多堆栈
[1] com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource (BasicResourcePool.java:201)
[2] com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection (C3P0PooledConnectionPool.java:232)
[3] com.mchange.v2.c3p0.PoolBackedDataSource.getConnection (PoolBackedDataSource.java:94)
[4] com.mchange.v2.c3p0.ComboPooledDataSource.getConnection (ComboPooledDataSource.java:521)
[5] org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection (LocalDataSourceConnectionProvider.java:82)
[6] org.hibernate.jdbc.ConnectionManager.openConnection (ConnectionManager.java:417)
[7] org.hibernate.jdbc.ConnectionManager.getConnection (ConnectionManager.java:144)
[8] org.hibernate.jdbc.JDBCContext.connection (JDBCContext.java:119)
[9] org.hibernate.transaction.JDBCTransaction.begin (JDBCTransaction.java:57)
[10] org.hibernate.impl.SessionImpl.beginTransaction (SessionImpl.java:1,326)
[11] org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin (HibernateTransactionManager.java:558)
[12] org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction (AbstractPlatformTransactionManager.java:374)
[13] org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary (TransactionAspectSupport.java:263)
[14] org.springframework.transaction.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:101)
[15] org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:171)
[16] org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept (Cglib2AopProxy.java:635)
看堆栈调用线程多阻塞在获取数据库连接时候,我查过数据配置连接池100-500 ,运行线程数量也没那么多,线程池里面数据库连接应该 没有用光的
查看了[1] com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource (BasicResourcePool.java:201)行代码其实是同步函数 .
网上对synchronized 解析如下
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块
网上搜索下类似问题,可以改成用jdbc来操作DB,效率也高,不过我不想改动太多代码,毕竟是老项目,改太多会造成不稳定
所以我想可不可以这样。减少对连接池的getConnection 调用,这样减少c3p0的线程阻塞,按照这样思路我把频繁调用保存DB的代码改成批量保存。
单独开个线程缓存对象列表 ,然后批量保存,代码如下,
@Override
public void saveListTransingTrade(final List<TransingTrade> listpo) {
// TODO Auto-generated method stub
hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session arg0) throws HibernateException,
SQLException {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
int count = 0;
for(TransingTrade t:listpo)
{
hibernateTemplate.saveOrUpdate(t);
if(count > 0&& count%SovtConfig.getInstance().getBatchsavecount() == 0)
{
arg0.flush();
arg0.clear();
}
count++;
}
arg0.flush();
arg0.clear();
log.error("batch save TransingTrade:" + listpo.size() + ",cost:"+(System.currentTimeMillis()-start));
return null;
}
});
}
改动经过测试后,放在公网运行后,发现即使在线人数3,4千人时候,也有不少空闲线程.登录游戏响应有明显提升
至于改动后性能测试,大家可以自己测试咯。主要是分享解决思路。
服务器出现无法登录时候,在服务器JDB 记录下多线程调用堆栈记录 以下是出现次数最多堆栈
[1] com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource (BasicResourcePool.java:201)
[2] com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection (C3P0PooledConnectionPool.java:232)
[3] com.mchange.v2.c3p0.PoolBackedDataSource.getConnection (PoolBackedDataSource.java:94)
[4] com.mchange.v2.c3p0.ComboPooledDataSource.getConnection (ComboPooledDataSource.java:521)
[5] org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection (LocalDataSourceConnectionProvider.java:82)
[6] org.hibernate.jdbc.ConnectionManager.openConnection (ConnectionManager.java:417)
[7] org.hibernate.jdbc.ConnectionManager.getConnection (ConnectionManager.java:144)
[8] org.hibernate.jdbc.JDBCContext.connection (JDBCContext.java:119)
[9] org.hibernate.transaction.JDBCTransaction.begin (JDBCTransaction.java:57)
[10] org.hibernate.impl.SessionImpl.beginTransaction (SessionImpl.java:1,326)
[11] org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin (HibernateTransactionManager.java:558)
[12] org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction (AbstractPlatformTransactionManager.java:374)
[13] org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary (TransactionAspectSupport.java:263)
[14] org.springframework.transaction.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:101)
[15] org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:171)
[16] org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept (Cglib2AopProxy.java:635)
看堆栈调用线程多阻塞在获取数据库连接时候,我查过数据配置连接池100-500 ,运行线程数量也没那么多,线程池里面数据库连接应该 没有用光的
查看了[1] com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource (BasicResourcePool.java:201)行代码其实是同步函数 .
网上对synchronized 解析如下
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块
网上搜索下类似问题,可以改成用jdbc来操作DB,效率也高,不过我不想改动太多代码,毕竟是老项目,改太多会造成不稳定
所以我想可不可以这样。减少对连接池的getConnection 调用,这样减少c3p0的线程阻塞,按照这样思路我把频繁调用保存DB的代码改成批量保存。
单独开个线程缓存对象列表 ,然后批量保存,代码如下,
@Override
public void saveListTransingTrade(final List<TransingTrade> listpo) {
// TODO Auto-generated method stub
hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session arg0) throws HibernateException,
SQLException {
// TODO Auto-generated method stub
long start=System.currentTimeMillis();
int count = 0;
for(TransingTrade t:listpo)
{
hibernateTemplate.saveOrUpdate(t);
if(count > 0&& count%SovtConfig.getInstance().getBatchsavecount() == 0)
{
arg0.flush();
arg0.clear();
}
count++;
}
arg0.flush();
arg0.clear();
log.error("batch save TransingTrade:" + listpo.size() + ",cost:"+(System.currentTimeMillis()-start));
return null;
}
});
}
改动经过测试后,放在公网运行后,发现即使在线人数3,4千人时候,也有不少空闲线程.登录游戏响应有明显提升
至于改动后性能测试,大家可以自己测试咯。主要是分享解决思路。
相关文章推荐
- 采用C3P0连接池解决spring+hibernate+mysql 访问空闲8小时后自动断开连接的问题
- “超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。”问题的解决方法
- 解决Android sdk manager启动时候获取资源列表比较慢的问题
- 解决12306.cn网站验证码获取提示“基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系“的问题
- volley 访问网络时候获取json数据发生乱码问题解决方法,以及gson解析json数据。
- 解决一个问题的思路 之“解决已经写满con.close() 仍然出现"但是尚未从池中获取连接"的连接池耗尽问题”
- 解决Java使用c3p0连接池连接mysql数据库出现MESSAGE: Software caused connection abort: socket write error的问题
- ssh 连接的时候 Host key verification failed.问题解决
- 彻底解决 Jedis 连接池 获取不到连接,连接放回连接池错误的问题
- 网络连接不能获取IP问题解决
- 如何解决ssh连接后长时间不操作断线的问题?
- 关于将RadioButtonList的AutoPostBack属性设置为"True"获取子项时候引起回发的问题解决方法
- 如何解决Java线程同步中的阻塞问题
- 解决 c3p0 和 MySQL 集成情况下,连接长时间闲置后重新使用时报错的问题
- 在从池中获取连接之前超时时间已过,所有池连接都已被使用并已达到最大池大小的问题解决方法
- 解决 c3p0 和 MySQL 集成情况下,连接长时间闲置后重新使用时报错的问题
- 如何解决ssh连接后长时间不操作断线的问题?
- 【rabbitmq】解决SimpleAmqpClient创建连接时阻塞的问题
- 解决SSIS连接ODBC数据源时“无法从运行时连接管理器获取托管连接”的问题
- C3P0连接池配置解决MySQL连接的空闲时间超过8小时后自动断开连接的问题