如何微调 JPA/JAX-RS 应用程序

How to fine-tune a JPA/JAX-RS application

我在 Wildfly/RESTeasy 中开发了一个带有 JPA/Hibernate 后端的 JAX-RS JSON API,但我有严重的数据库访问问题。

例如,应用程序突然停止响应,日志显示一堆:

ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (EJB default - 4) IJ031012: Unable to obtain lock in 60 seconds: org.jboss.jca.adapters.jdbc.local.LocalManagedConnection

INFO  [org.jboss.jca.core.connectionmanager.listener.TxConnectionListener] IJ000302: Unregistered handle that was not registered: org.jboss.jca.adapters.jdbc.jdk7.WrappedConnectionJDK7

WARN  [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] IJ000609: Attempt to return connection twice: org.jboss.jca.core.connectionmanager.listener.TxConnectionListener

WARN  [org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (default task-9) IJ030020: Detected queued threads during cleanup

ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ForkJoinPool.commonPool-worker-0) IJ031041: Connection handle has been closed and is unusable

ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (ForkJoinPool.commonPool-worker-1) IJ031050: The result set is closed

我认为这是由于不同用户的多次访问(比如同时有 15、20 个用户),因为 one/two 用户不会发生这种情况。

我使用的是 Hibernate 5.1 和 Wildfly 10,以及 SQL Server 2014。这是一个原始安装,没有调整或自定义配置。如何微调基础架构以避免这些问题?

使用 HikariCP 连接池。 根据您的流量配置连接池和数据库中的连接数。 在连接池中,可以选择始终保持一定数量的连接可用。并将连接隔离类型设置为仅提交后。

下面是它的示例,

<persistence-unit name="sample" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>

            <!-- provider -->
            <property name="hibernate.connection.provider_class" value="com.xo.web.persistence.XOHikariCPConnectionProvider"/>

            <!-- Hibernate properties -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.archive.autodetection" value="hbm" />
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="show_sql"  value="false"/>
            <property name="hibernate.connection.release_mode" value="after_transaction"/>
            <property name="hibernate.connection.autocommit" value="false"/>
            <property name="hibernate.connection.isolation" value="2"/>
            <property name="hibernate.ejb.interceptor" value="com.xo.web.persistence.intercept.XoEntityInterceptor"/>
            <property name="hibernate.jdbc.batch_size" value="100"/>
            <property name="hibernate.order_inserts" value="true"/>
            <property name="hibernate.order_updates" value="true"/>


            <!-- Hikari settings -->
            <property name="maximumPoolSize" value="80" />
            <property name="autoCommit" value="false" />
            <property name="minimumPoolSize" value="20" />
            <property name="idleTimeout" value="60000" />
            <property name="maxLifetime" value="600000" />
            <property name="connectionInitSql" value="select 1" />
            <property name="connectionTimeout" value="1000" />
            <property name="validationTimeout" value="1000" />
            <property name="cachePrepStmts" value="true" />
            <property name="prepStmtCacheSize" value="250" />
            <property name="prepStmtCacheSqlLimit" value="2048" />

        </properties>
    </persistence-unit> 

问题与 REST 服务有关 @Stateless,因此在每个请求上打开交易。解决方案是将 @Stateless DAO 注入 REST 服务:不再有锁定问题。