zoukankan      html  css  js  c++  java
  • 另类解决c3p0连接池获取连接时候长时间阻塞线程问题

    一直维护着旧游戏服务器 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千人时候,也有不少空闲线程.登录游戏响应有明显提升

    至于改动后性能测试,大家可以自己测试咯。主要是分享解决思路。

  • 相关阅读:
    CentOS7学习小记
    PHP的time函数返回时间不正确
    MySQL信息提示不是英文问题
    windows下ITOP安装
    Zend安装
    投资日记2015.6
    解决SecureCRT连接linux超时后断开[转]
    红黑树及生成超过32768随机数
    在宏定义中怎么使用可变参数
    C++堆上申请二维数组
  • 原文地址:https://www.cnblogs.com/maikkk/p/6591608.html
Copyright © 2011-2022 走看看