带有 Infinispan 和 JBoss EAP 7.0.6 的休眠 L2C 不工作

Posted

技术标签:

【中文标题】带有 Infinispan 和 JBoss EAP 7.0.6 的休眠 L2C 不工作【英文标题】:Hibernate L2C with Infinispan and JBoss EAP 7.0.6 is not working 【发布时间】:2018-02-01 01:22:23 【问题描述】:

我有一个使用 Hibernate 5.0.9.Final 的应用程序部署到 JBoss EAP 7.0.6(默认使用 Infinispan 8.0.1.Final)。必须缓存几个实体,它们使用 JPA 的 @Cacheable 和 Hibernate 的 @Cache 进行注释,以提供每个实体的缓存策略。

代码库包含一个简单的测试,它检查 Infinispan 在本地与测试用例一起运行并直接访问数据源,也就是说,两者之间没有 JBoss EAP,也没有 Arquillian 测试。测试成功运行,我可以看到在可用时从缓存中获取实体。

现在将应用程序部署到 JBoss EAP 并运行会导致负面体验。我可以在日志中看到 Infinispan 缓存实体。我还可以在 JBoss Web 控制台上看到缓存统计信息。当一个应该导致缓存命中计数的查询被执行时,结果是没有命中计数发生,而是查询命中了数据源。

更新: 已使用 persistence.xml 中的适当属性启用了休眠和 infinispan 统计信息; L2C 和查询缓存也是如此。区域工厂设置为JndiInfinispanRegionFactory,如http://infinispan.org/docs/8.0.x/user_guide/user_guide.html 中所述。此外,所有执行的查询都是 JPQL 查询。据我所知,告诉 Infinispan 和 JBoss AS/7 使用他们的默认配置。

更新 2: JBoss 服务器实际上是 EAP 7.0.6,而不是前面所述的 AS/7。

目前我们无法升级到更新版本的 JBoss EAP(恐怕现在还没有 Wildfly)。

顺便说一句,尝试在本地运行 EhCache 是成功的,但在 JBoss EAP 中运行会由于模块问题导致 CNFE。

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
            xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="DefaultUnit" transaction-type="JTA">
       <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
       <jta-data-source>java:/MyDataSource</jta-data-source>
       <class>...</class>
       <exclude-unlisted-classes>true</exclude-unlisted-classes>
       <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
       <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
           <property name="hibernate.show_sql" value="true" />
           <property name="hibernate.connection.datasource" value="java:/MyDataSource"/>
           <property name="hibernate.generate_statistics" value="true" />
           <property name="hibernate.cache.infinispan.statistics" value="true"/>
           <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
           <property name="hibernate.cache.use_second_level_cache" value="true" />
           <property name="hibernate.cache.use_query_cache" value="true" />
           <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory"/>
           <property name="hibernate.cache.infinispan.cachemanager" value="java:jboss/infinispan/container/hibernate"/>
       </properties>
   </persistence-unit>
</persistence>

standalone.xml 这个块定义了休眠容器

<cache-container name="hibernate" default-cache="local-query" module="org.hibernate.infinispan">
    <local-cache name="entity">
        <transaction mode="FULL_XA"/>
        <eviction strategy="LRU" max-entries="10000"/>
        <expiration max-idle="100000"/>
    </local-cache>
    <local-cache name="local-query">
        <eviction strategy="LRU" max-entries="10000"/>
        <expiration max-idle="100000"/>
    </local-cache>
    <local-cache name="timestamps"/>
</cache-container>

【问题讨论】:

Andres,您的部署中是否包含 Infinispan 和/或 Hibernate jar?只是想知道是否使用了错误的东西。另外,我认为您使用的 persistence.xml 配置是错误的。查看EAP 7 documentation,其中详细说明了用于启用 Infinispan 2LC 的属性。 特别是,仅使用文档说明的属性并删除区域工厂定义。这当然是假设您使用的是 EAP 提供的 Hibernate 和 Infinispan 版本... 查看 here 以获取去除配置中多余元素的 persistence.xml。 Galder,Hibernate 被设置为提供范围内的依赖项。 Infinispan 未定义为生产依赖项,因为它预计是 EAP 的内部设置。 Infinispan 仅设置为测试依赖项。 好的,那么您绝对应该按照要点所示配置持久性 XML。我们现有的 EAP 粘合代码为您完成了所有艰苦的工作。 【参考方案1】:

当一个应该导致缓存命中计数的查询被执行时,它 结果没有发生命中计数并且查询命中数据源 而是。

当您说查询时,您是指 JPQL 查询还是 Criteria API?

实体查询旨在通过实体标识符直接获取。对于查询,您还需要查询缓存,但不清楚这是否是您所需要的。

此外,如果未启用统计信息,则命中计数可以为 0:

与 Hibernate Core 相关的 hibernate.generate_statistics 之一 或者,hibernate.cache.infinispan.statistics,代表 Infinispan

找出发生了什么的一种方法是调试DefaultLoadEventListener#doLoad 方法:

entity = loadFromSecondLevelCache( event, persister, keyToLoad );

看看为什么它不能从 Infinispan 获取。

更新:

此外,所有执行的查询都是 JPQL 查询。

您是否启用了查询缓存?

请注意,查询缓存使用单个区域,因此一旦您添加/删除/修改属于该表空间的任何单个条目,所有使用某个表空间的查询结果都会被清除。

如果您在尝试加速 JPQL 时依赖实体 2 级缓存而不使用查询缓存,那么它的工作效率将低于没有 2 级缓存的情况。那是因为 JPQL 无论如何都会执行 SQL 查询,因此您只需丢弃结果并转到缓存以通过其 id 获取实体。如果在缓存中找不到实体,这实际上会变得非常糟糕,这意味着将发出过多的辅助查询。

如果您在执行读写事务时尝试卸载主节点,则二级缓存非常有意义。对于只读查询,只需使用数据库复制并将负载分散到多个副本上,这些副本的缓冲池配置为将整个工作集存储在 RAM 中。

【讨论】:

感谢弗拉德,我在问题中添加了更多细节。基本上我们遵循 infinispan.org/docs/8.0.x/user_guide/user_guide.html 并启用了 Hibernate 和 Infinispan 的统计信息。 是的,查询缓存已启用。我们正在测试设置缓存的水域,因此目前使用单个区域。 对于查询缓存,只有一个区域:StandardQueryCache。我不认为 Hibernate 可以为查询缓存使用更多的查询结果区域。【参考方案2】:

我强烈建议避免这种组合:

JBoss AS7 陈旧到无法与 Java 8 完全兼容的地步 Infinispan 8 需要 Java 8

由于您声明您无法升级到 WildFly(即将推出 11 个!),因此您落后了近 4 个主要版本:这是很多缺失的错误修复和改进,但在您的几代库中也存在显着差异'重新组合。

我建议:

坚持使用 Ehcache 坚持使用应用服务器中包含的旧版本 Hibernate ORM WildFly 11 更新 :-) 获取受支持的 JBoss EAP 7.x

对于 EAP 的商业参考,我深表歉意,但它可能是一个很好的解决方案,具体取决于您无法升级到 WildFly 的原因,因为它本质上是结合了更高版本(尤其是向后移植的兼容性修复)和严格的 API 向后兼容性政策。

关于 Ehcache 让您在模块方面遇到麻烦,我很乐意为您提供帮助。模块系统很棒,我相信这可能很容易解决,但作为不同的问题/论坛处理可能会更好。

【讨论】:

知道了。 EhCache 主题发布于***.com/questions/45841056/… 顺便说一下,我们使用的实际 JBoss 版本是 7.0.6 EAP ;-)【参考方案3】:

persistence.xml 配置不正确。部署到 EAP 时,只需这样做:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="DefaultUnit" transaction-type="JTA">
       <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
       <jta-data-source>java:/MyDataSource</jta-data-source>
       <class>...</class>
       <exclude-unlisted-classes>true</exclude-unlisted-classes>
       <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
       <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
           <property name="hibernate.show_sql" value="true" />
           <property name="hibernate.connection.datasource" value="java:/MyDataSource"/>
           <property name="hibernate.generate_statistics" value="true" />
           <property name="hibernate.cache.infinispan.statistics" value="true"/>
           <property name="hibernate.cache.use_second_level_cache" value="true" />
           <property name="hibernate.cache.use_query_cache" value="true" />
       </properties>
   </persistence-unit>
</persistence>

通过定义您自己的区域工厂,您可能会冒着不使用由您正在检查统计信息的 EAP 管理的实际 Infinispan 实例的风险。

查看EAP 7 documentation 了解更多信息。

【讨论】:

以上是关于带有 Infinispan 和 JBoss EAP 7.0.6 的休眠 L2C 不工作的主要内容,如果未能解决你的问题,请参考以下文章

JBoss EAP 6.4 Infinispan 集群缓存网络问题

为啥休眠 5.3 不支持带有 infinispan 的事务缓存

Infinispan 集群同步问题

带有 websocket 和 stockjs 的 JBOSS eap 6.3 beta - 使用 spring 框架的 stomp.js

带有需要重新加载命令的 Jboss EAP 6 CLI 脚本

带有 Infinispan 目录提供程序的 Hibernate Search 6