代码之家  ›  专栏  ›  技术社区  ›  hirtenfelder

使用Hibernate搜索时,由于lucene锁定,Spring Boot集成测试失败

  •  1
  • hirtenfelder  · 技术社区  · 7 年前

    在我的Spring Boot 1.5.10中。最后一个项目我使用Hibernate Search ORM 5.6.4。最终的除了集成测试之外,它工作正常。有一个测试类和几个 测试搜索逻辑的测试方法。如果我只运行这个测试类,一切都会很好。Spring Boot正在启动并创建索引。如果我运行这个测试类 与所有其他集成测试一起,每个测试类都将抛出一个LockObtainFailedException,Hibernate搜索测试将失败。

    org.apache.lucene.store.LockObtainFailedException: Lock held by this virtual machine: ...LieferantEntity\write.lock
        at org.apache.lucene.store.NativeFSLockFactory.obtainFSLock(NativeFSLockFactory.java:127) ~[lucene-core-5.5.5.jar:5.5.5 b3441673c21c83762035dc21d3827ad16aa17b68 - sarowe - 2017-10-20 08:57:09]
        at org.apache.lucene.store.FSLockFactory.obtainLock(FSLockFactory.java:41) ~[lucene-core-5.5.5.jar:5.5.5 b3441673c21c83762035dc21d3827ad16aa17b68 - sarowe - 2017-10-20 08:57:09]
        at org.apache.lucene.store.BaseDirectory.obtainLock(BaseDirectory.java:45) ~[lucene-core-5.5.5.jar:5.5.5 b3441673c21c83762035dc21d3827ad16aa17b68 - sarowe - 2017-10-20 08:57:09]
        at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:776) ~[lucene-core-5.5.5.jar:5.5.5 b3441673c21c83762035dc21d3827ad16aa17b68 - sarowe - 2017-10-20 08:57:09]
        at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.createNewIndexWriter(IndexWriterHolder.java:126) ~[hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.getIndexWriter(IndexWriterHolder.java:92) ~[hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriter(AbstractWorkspaceImpl.java:117) ~[hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriterDelegate(AbstractWorkspaceImpl.java:203) ~[hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.applyUpdates(LuceneBackendQueueTask.java:81) [hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.run(LuceneBackendQueueTask.java:46) [hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.applyChangesets(SyncWorkProcessor.java:165) [hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.run(SyncWorkProcessor.java:151) [hibernate-search-engine-5.6.4.Final.jar:5.6.4.Final]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
    

    我使用默认设置。如果我将exclusive\u index\u use设置为false,那么它可以正常工作,但测试执行非常缓慢。 对我来说,索引似乎是在Spring Boot启动期间初始化的,并且会干扰测试。

    是否可以将Spring Boot集成测试与Hibernate搜索结合使用,以便在测试之间干净地释放锁? 另外,我正在寻找一种方法来禁用所有未使用Hibernate搜索的集成测试的Hibernate搜索索引

    我还尝试了接近实时的财产和不同的锁工厂,作为本地的,简单的和单一的没有运气。

    1 回复  |  直到 7 年前
        1
  •  6
  •   yrodiere    3 年前

    第一:不要使用 exclusive_index_use 除非你是Lucene大师。这很危险,可能不会像你想的那样。

    现在我们已经解决了这个问题。。。据我所知,您正在尝试在同一台机器上并行执行集成测试。这意味着集成测试可能会竞争访问完全相同的索引,并写入相同的索引。如果您的测试执行冲突写入(一个测试在测试完成之前擦除另一个测试添加的文档),这可能会导致不可预测的结果。

    如果确实需要并行执行测试,我建议在隔离环境中执行每个测试:

    • 专用数据库,或至少专用数据库架构
    • 专用Lucene索引

    在Hibernate搜索的情况下,您必须找到在每次测试执行中使用不同物理索引的方法。

    有两种方法可以做到这一点:

    1. 对于测试,不要将索引存储在文件系统上,而是通过设置 hibernate.search.backend.directory.type local-heap (休眠搜索6+)或 hibernate.search.default.directory_provider 本地堆 (休眠搜索5及以下)。

    它非常容易实现,但您应该注意以下几个缺点:

    • 您的测试环境将不再与生产环境完全相同
    • 测试完成后,索引将丢失,这可能会使事后调试具有挑战性(您将无法再使用Luke检查索引的状态)
    • 如果您的集成测试在索引中存储了大量内容,那么您可能会得到 OutOfMemoryError
    1. 如果解决方案1的缺点对您来说太多,您可以继续使用文件系统来存储索引,但对每个测试执行使用不同的配置,设置索引基路径( hibernate.search.backend.directory.root 对于Hibernate Search 6+,或 hibernate.search.default.indexBase 对于Hibernate Search 5及以下版本),每个测试执行的路径都是唯一的。你必须在春天找到如何做到这一点,但我很惊讶地发现这是不可能的。也许Spring允许您在属性中使用插值,比如 hibernate.search.backend.directory.root = /tmp/it/#{testName} ?

    请参阅有关目录配置的文档( here for Hibernate Search 6+ here for Hibernate Search 5 有关如何配置索引存储的详细信息。