当前位置: 首页 > 知识库问答 >
问题:

SpringMVC、c3p0、hibernate、JPA应用程序泄漏连接导致连接错误过多

仇航
2023-03-14

我已经在谷歌上搜索了4个多小时的stackoverflow来寻找我的问题的解决方案,阅读并试图了解正在发生的事情,但我没有遇到与我的问题相关的解决方案,所以抱歉,如果这听起来像是重复的,我会尽力解释到底发生了什么,这样我就可以深入了解C3P0的内部工作。

我有一个运行在Tomcat上的SpringMVC web应用程序,其中Hibernate、JPA和C3P0是我的池资源。重新加载页面时,应用程序会对数据库进行几次调用,以获取随机图像并将其显示在新页面上。应用程序可以正常运行大约30个页面,但最终总是崩溃,我必须重新启动mysql,以使应用程序再次工作,它给出以下错误:

下面是相关的文件/配置,以提供问题的上下文:

spring.xml:

<context:component-scan base-package="com.clathrop.infographyl.dao" />

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="infographylPU" />
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <!-- Connection properties -->
    <property name="driverClass" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/infographyl_db" />
    <property name="user" value="user" />
    <property name="password" value="passwd" />
    <!-- Pool properties -->
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="20" />
    <property name="acquireIncrement" value="1" />
    <property name="maxStatements" value="0" />
    <property name="idleConnectionTestPeriod" value="3000" />
    <property name="loginTimeout" value="300" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

persistence.xml:

<persistence-unit name="infographylPU" transaction-type="RESOURCE_LOCAL">
    <class>com.clathrop.infographyl.model.Infographic</class>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
    </properties>
</persistence-unit>
@Repository
public class InfographicDaoImpl implements InfographicDao{

@PersistenceContext
private EntityManager entityManager;

@Override
@Transactional
public void insertInfographic(Infographic infographic){
    try{
        entityManager.persist(infographic);
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        entityManager.close();
    }

}

@Override
public List<Infographic> findAllInfographics(){
    try{
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Infographic> cq = builder.createQuery(Infographic.class);

        Root<Infographic> root = cq.from(Infographic.class);
        cq.select(root);
        List<Infographic> igList = entityManager.createQuery(cq).getResultList();
        return igList;
    } catch (Exception e){
        e.printStackTrace();
        return null;
    } finally {
        entityManager.close();
    }
}

@Override
public Infographic getRandomInfographic(Integer tableSize){
    Random rand = new Random();
    int randomIndex = rand.nextInt((tableSize-1)+1) + 1;

    try{
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Infographic> cq = builder.createQuery(Infographic.class);

        Root<Infographic> root = cq.from(Infographic.class);
        cq.select(root);
        cq.where(builder.equal(root.<Integer>get("id"), randomIndex));
        Infographic randomIg = entityManager.createQuery(cq).getSingleResult();
        return randomIg;
    } catch (Exception e){
        e.printStackTrace();
        return null;
    } finally {
        entityManager.close();
    }


}

@Override
public Integer getRowCount(){
    try{
        Number result = (Number) entityManager.createNativeQuery("Select count(id) from infographics").getSingleResult();
        return result.intValue();
    } catch (Exception e){
        e.printStackTrace();
        return null;
    } finally {
        entityManager.close();
    }
}

@Override
public List<Infographic> listInfographics(Integer startIndex, Integer pageSize){
    List<Infographic> igList = new ArrayList<Infographic>();

    String sStartIndex = Integer.toString(startIndex);
    String sPageSize = Integer.toString(pageSize);

    try{
        List list = entityManager.createNativeQuery("Select * from infographics limit " + sStartIndex + ", " + sPageSize).getResultList();
        for(Object ig : list){
            igList.add((Infographic) ig);
        }
        return igList;
    } catch(Exception e){
        e.printStackTrace();
        return null;
    } finally {
        entityManager.close();
    }


}

更新:

严重:web应用程序[/Infographyl]似乎已启动名为[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0]的线程,但未能停止它。这很有可能造成内存泄漏。

我已经将问题缩小到一个内存泄漏,在tomcat启动并部署所讨论的应用程序时会发现这个问题。我现在的问题是试图查找导致问题的可能配置(或缺少配置)。

2015年04月05日10:57:30 PM org.hibernate.service.jdbc.connections.internal.connectionProviderInitiator实例化ExplicitConnectionProvider信息:hhh000130:实例化显式连接提供程序:org.hibernate.ejb.connection.injectedDatasourceConnectionProvider 2015年04月05日10:57:30 PM com.mchange.v2.c3p0.impl.abstractPoolbackedDatasource getPoolManager信息:正在初始化c3p0池...com.mchange.v2.c3p0.CombopooledDataSource[acquireIncrement->1,AcquireTretyActempts->30,AcquireTretyDelay->1000,autoCommitOnClose->false,automaticTestTable->null,breakAfterAcquireFailure->false,checkoutTimeout->0,connectionCustomizerClassName->null,connectionTesterClassName->com.mchange.v2.c3p0.impl.DefaultConnectionTester,->3,numThreadsAwaitingCheckoutDefaultUser->0,preferredTestQuery->null,properties->{user=******,password=******},propertyCycle->0,testConnectionOnCheckin->false,testConnectionOnCheckout->false,UnreturndConnectionTimeout->0,usesTraditionalReflectiveProxies->false]

共有1个答案

纪鸿禧
2023-03-14

因此,从您描述的所有内容来看,听起来您的应用程序是在创建多个c3p0池,然后放弃多个c3p0池。您不会遇到单个池耗尽(应用程序冻结)的常见症状。相反,您的应用程序打开的连接比maxPoolSize多,然后当它达到服务器端连接限制时失败。除非您的服务器东西~20个连接太多,否则您很可能正在创建多个池。设置wait_timeout隐藏了这个问题,因为放弃的数据源的连接会自动关闭()ed,但这不是一个好的解决方案。如果您正在为每个客户机创建新的数据源,您将大大减慢而不是加快您的应用程序,并且如果这些数据源没有关闭(似乎没有关闭,或者您没有积累打开的连接),您将创建线程和内存泄漏。

所以。

首先,你是如何伐木的?请确保com.mchange.*类已在INFO处记录,并选中“查找池初始化消息”。c3p0在数据源初始化的INFO处转储一个大的池配置消息。确保至少看到其中一条消息。你见过他们很多次吗?那么这就是问题所在。

 类似资料:
  • 我在做java企业应用。该应用程序后端有hibernate框架。由于应用程序中最近的更改,一些代码消耗了weblogic server中的所有JDBC连接池。 应用程序连接是在代码中进行属性处理,对于每个线程,我们使用threadlocal类创建每个会话。所以创建连接没有问题。该应用程序已存在5年以上。 我们怀疑最近的代码更改会导致此主要问题。最后,我们决定使用探查器工具来调查此问题。 在此之前,

  • 我在webapp(hibernate-core-4.3.8。Final和Spring 3.2.11。RELEASE)上使用Spring和hibernate。我使用hikaricp(v 2.2.5)作为连接池impl,它检测连接泄漏并打印下面的stacktrac。我使用Spring的声明性事务划分,因此我假设资源的管理和清理是由Spring/hibernate完成的。因此,我认为Spring或hib

  • 我正在运行一个Spring boot Java应用程序,使用默认的HikariCP作为数据源: Hikari版本-3.4.5 在AWS EKS中运行的Spring Boot version-2.4.5 JDBI版本-3.9.1 DB-AWS RDS Postgres 我的Spring应用程序变得没有响应,因为它失去了Hikari池中的所有连接。这并不是确定地发生,但是一旦它开始发生,唯一可能的恢复

  • 我正在开发一个在Java服务器上运行的游戏。对于数据库池,我使用的是HikariCP,这是一个优秀的库,但它现在抛出了以下错误: 现在我知道连接泄漏意味着打开的连接在某个地方漂浮,但我不知道如何或在哪里漂浮。 下面是我的数据库类中的一个方法,根据堆栈跟踪,错误应该发生在这里。 这只是启动语句的一个基本方法。调用它时,我使用它,然后调用、和 但它告诉我连接是打开的。 我怎么解决这个?谢了!

  • 是否可以在2.3.9版本中启用泄漏检测?正如我之前在这个问题中所说,HiberNate使用的是HikariCP的2.3.3版本。截至2016年2月,他们已经升级了HikariCP的版本,但不幸的是升级到了2.3.9版本 我需要启用泄漏检测才能修复它们。我已将以下行添加到Hibernate配置文件中: 前两行运行正常,可以在调试日志中看到,但是当我添加第三行时,我无法运行应用程序。我也尝试过用代码添

  • 我有一个带有和对象的。每次调用,我都会执行以下操作: 我不关闭,因为没有关闭方法。每次调用servlet时,mongo中使用的连接数都会增加: 什么是与mongo和morphia建立联系的正确方式?这种联系到底在哪里?谢谢