Infinispan/JDBC 作为 Wildfly/JBoss 上 Hibernate Search 的后端

Posted

技术标签:

【中文标题】Infinispan/JDBC 作为 Wildfly/JBoss 上 Hibernate Search 的后端【英文标题】:Infinispan/JDBC as Backend for Hibernate Search on Wildfly/JBoss 【发布时间】:2017-07-26 13:14:59 【问题描述】:

我正在尝试配置一个 JDBC 支持的 Infinispan 缓存,作为我的 Java EE 应用程序使用 Hibernate Search 的后端。我在 JBoss EAP 7.0 或 Wildfly 10 上进行部署。我有一个模块、缓存容器和 persistence.xml 配置,在启动时不会给我任何错误。此外,我能够创建 JPA 对象并按预期通过 Hibernate Search 对它们进行索引。然后我就可以成功查询这些对象了。但是,在任何时候都不会在我配置为缓存容器的 JDBC 数据源的数据库中创建 SQL 表。因此,很明显,搜索索引只存在于内存中,并且不会在应用服务器重启后持续存在。这是我迄今为止所做的:

    下载了对应于嵌入在 JBoss EAP 中的 Infinispan 版本的 Infinispan 8.1.x 版本。这样做是因为 Infinispan 的休眠搜索模块不包含在嵌入式模块中 我已经为 JBoss EAP 中的 Infinispan hibernate-search 模块配置了适当的模块 修改了我的 Standalone-full-ha.xml JBoss EAP 配置文件以包含一个 JDBC 支持的缓存容器和缓存定义 修改了我的 persistence.xml 文件以使用 Infinispan 缓存管理器和目录提供程序

这是我在standalone-full-ha.xml中找到的缓存容器的定义:

 <cache-container name="hibernateSearch" default-cache="LuceneIndexesData" module="org.infinispan.cachestore.jdbc" jndi-name="java:jboss/infinispan/hibernateSearch">
            <transport lock-timeout="60000"/>
            <replicated-cache name="LuceneIndexesMetadata" statistics-enabled="true" mode="SYNC">
                <binary-keyed-jdbc-store data-source="InfinispanCacheDS" passivation="false" purge="false" shared="true">
                    <binary-keyed-table>
                        <id-column name="ID_COLUMN" type="VARCHAR(255)"/>
                        <data-column name="DATUM" type="BYTEA"/>
                    </binary-keyed-table>
                </binary-keyed-jdbc-store>
            </replicated-cache>
            <replicated-cache name="LuceneIndexesData" statistics-enabled="true" mode="SYNC">
                <binary-keyed-jdbc-store data-source="InfinispanCacheDS" passivation="false" purge="false" shared="true">
                    <binary-keyed-table>
                        <id-column name="ID_COLUMN" type="VARCHAR(255)"/>
                        <data-column name="DATUM" type="BYTEA"/>
                    </binary-keyed-table>
                </binary-keyed-jdbc-store>
            </replicated-cache>
            <replicated-cache name="LuceneIndexesLocking" statistics-enabled="true" mode="SYNC"/>
        </cache-container>

这是我的来自standalone-full-ha.xml 的 JDBC 数据源:

<datasource jndi-name="java:jboss/datasources/InfinispanCacheDS" pool-name="InfinispanCacheDS" enabled="true" use-java-context="true" statistics-enabled="true">
                <connection-url>jdbc:postgresql://localhost:5432/db_infinispan_cache</connection-url>
                <driver>postgresql-jdbc4</driver>
                <pool>
                    <min-pool-size>10</min-pool-size>
                    <max-pool-size>20</max-pool-size>
                    <prefill>true</prefill>
                    <flush-strategy>IdleConnections</flush-strategy>
                </pool>
                <security>
                    <user-name>infinispan_cache</user-name>
                    <password>mypassword</password>
                </security>
                <validation>
                    <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
                    <validate-on-match>true</validate-on-match>
                    <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
                </validation>
                <statement>
                    <track-statements>true</track-statements>
                </statement>
            </datasource>

这是我的 persistence.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
    version="2.1">

    <persistence-unit name="MyPU" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/jdbc/datasources/MyDataSourceDS</jta-data-source>
        <shared-cache-mode>ALL</shared-cache-mode>

        <properties>
            <property name="jboss.entity.manager.factory.jndi.name"
                value="java:/MyDataSourceEntityManagerFactory" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />

            <property name="hibernate.jdbc.batch_size" value="50" />

            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="true" />

            <property name="hibernate.generate_statistics" value="true" />
            <property name="hibernate.connection.release_mode" value="auto" />

            <!-- Transactions -->
            <property name="hibernate.transaction.jta.platform"
                value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
            <property name="hibernate.transaction.flush_before_completion"
                value="true" />
            <property name="hibernate.transaction.manager_lookup_class"
                value="org.hibernate.transaction.JBossTransactionManagerLookup" />

            <property name="hibernate.max_fetch_depth" value="5" />

            <!-- Caching support - Infinispan -->
            <property name="hibernate.cache.use_second_level_cache"
                value="true" />

            <property name="hibernate.cache.infinispan.cachemanager"
                value="java:jboss/infinispan/container/hibernate" />
            <property name="hibernate.cache.use_second_level_cache"
                value="true" />

            <!-- Hibernate Search properties - Generic -->
            <property name="hibernate.search.reader.strategy" value="shared" />
            <property name="hibernate.search.worker.execution" value="sync" />
            <property name="hibernate.search.jmx_enabled" value="true" />

            <!-- Hibernate Search properties - Infinispan -->
            <property name="hibernate.search.infinispan.cachemanager_jndiname"
                value="java:jboss/infinispan/hibernateSearch" />
            <property name="hibernate.search.default.directory_provider"
                value="infinispan" />
            <property name="hibernate.search.infinispan.chunk_size"
                value="300000000" />

        </properties>
    </persistence-unit>
</persistence>

当 JBoss 启动时,我没有看到任何错误。但是,我也没有看到对 JDBC 的任何引用。在持久化 JPA 对象时,我也没有看到任何错误,因此似乎它们被适当地索引了。只是我的 Hibernate Search 索引没有像我预期的那样保存在数据库中。

谁能解释一下我在这里遗漏了什么?

【问题讨论】:

【参考方案1】:

如您所见,Hibernate Search 用于此目的的 Infinispan 扩展不包含在作为 WildFly / JBoss EAP 一部分的 Infinispan 模块中,因此您从 Infinispan 项目正确下载了 Infinispan 模块。

您缺少的是 WildFly 能够非常有效地隔离模块,因此您首先要意识到的是,您实际上不必匹配 WildFly 中包含的 Infinispan 版本。

由于您将使用来自 infinispan.org 的模块集,您不应该在您的 JBoss EAP 配置文件中配置这些缓存,因为那里定义的缓存由集群子系统控制,并且会影响由 Infinispan 创建的缓存定义WildFly 中包含的模块(插槽“main”中的 Infinispan 模块)。

您应该在基于 Hibernate Search 的应用程序中包含一个 Infinispan 配置文件,并让它使用正确的模块启动一个新的 CacheManager。

或者,您可以创建另一个应用程序以任何您喜欢的方式启动 CacheManager - 只要您依赖正确的 Infinispan 模块(避免“主”插槽) - 然后将其注册到 JNDI 并让 Hibernate Search 查找它名字。

注意Hibernate Search 模块依赖于 optional Infinispan 模块,因此如果存在,它将尝试加载正确的 Infinispan 模块:

https://github.com/wildfly/wildfly/blob/84d88b8/feature-pack/src/main/resources/modules/system/layers/base/org/hibernate/search/engine/main/module.xml#L53

还要注意,借助模块系统,您可以覆盖/升级 Hibernate Search 版本。 就版本而言,您的限制是:

选择与您选择的 Hibernate Search 版本兼容的 Infinispan 模块版本

选择与所选 Hibernate ORM 版本兼容的 Hibernate Search 版本

(没错,you can override / upgrade Hibernate ORM as well)。

假设您使用的是 WildFly 10 中包含的默认版本的 Hibernate ORM 和 Hibernate Search,您可以下载版本 8.2.6.Final(最新稳定版本)的 Infinispan 模块,因为它还包含一个模块

<module name="org.infinispan.hibernate-search.directory-provider" slot="for-hibernatesearch-5.5" >

或者,如果您使用 JBoss EAP,您可能更喜欢下载 JBoss Data Grid 发行版,它包含与 Infinispan 模块相同的功能。

【讨论】:

我有 Hibernate Search 正确写入 Inifnispan 缓存(据我所知)。磁盘上没有创建索引文件。当我执行 Hibernate Search 查询时,结果按预期返回。因此,在我看来,数据正在存储在 Infinispan 中,只是没有按照我预期的方式保存在我的 SQL 数据库中。所以在我看来,我的缓存容器定义存在问题,导致它不使用 JDBC 缓存存储。我就是不知道具体是什么问题。 我还应该提到我没有使用来自 infinispan.org 的完整 Infinispan 模块集。我只是为 Wildfly Infinispan 模块集中未包含的 JAR 文件创建模块。此外,我没有在我的 WAR 文件中嵌入 Hibernate/Hibernate 搜索。我也在使用 Wildfly 提供的模块。 您应该在 PostgreSQL 数据库中拥有正确的表,否则我们应该会看到错误。我不确定是哪一个,但要么它实际上没有使用 Infinispan DirectoryProvider,要么我们没有看到错误。我想你检查了日志?索引操作发生在不同的线程中,因此您的主应用程序可能不会注意到。您需要检查日志或配置替代 ErrorHandler:docs.jboss.org/hibernate/stable/search/reference/en-US/…

以上是关于Infinispan/JDBC 作为 Wildfly/JBoss 上 Hibernate Search 的后端的主要内容,如果未能解决你的问题,请参考以下文章

在 Wildfly 10 上运行 EJB 2.1

数组作为方法参数- 数组作为方法返回值

使用对象类型作为方法的参数和作为方法的返回值

使用 Keycloak 作为授权服务器,Zuul 作为 API 网关

输入对象数组作为输入并返回一个数组作为存储过程的输出

Kotlin函数 ⑧ ( 函数引用 作为函数参数 | ::函数名 | 函数类型 作为函数返回值类型 )