2013-08-06 12 views
5

Webアプリケーション上の項目をインデックス化し、フルテキスト検索するのに、Hibernate Searchを使用します。私のpom.xmlからLucene/Hibernate Searchロック例外

:さて、本番に行く前に、私は、ApacheのJMeterを使用して自分のWebアプリケーションの検索機能をストレステストしようとした

<hibernate.search.version>3.4.2.Final</hibernate.search.version> 
<apache.lucene.version>3.6.2</apache.lucene.version> 
<apache.solr.version>3.6.2</apache.solr.version> 
<hibernate.version>3.6.9.Final</hibernate.version> 

。もっとして一つのスレッドでテストするとき、私は次の例外のトンを受け取る:

私のインデックス作成は、(@Transactionalメソッドから呼び出された)次の関数を使用して行われ
17:11:57,670 ERROR LogErrorHandler:82 - Exception occurred org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: [email protected]/opt/myapp/item_index/myapp.item.domain.Item/write.lock 
Primary Failure: 
    Entity myapp.item.domain.Item Id 4 Work Type org.hibernate.search.backend.DeleteLuceneWork 
org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: [email protected]/opt/myapp/item_index/myapp.item.domain.Item/write.lock 
    at org.apache.lucene.store.Lock.obtain(Lock.java:84) 
    at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:1098) 
    at org.hibernate.search.backend.Workspace.createNewIndexWriter(Workspace.java:202) 
    at org.hibernate.search.backend.Workspace.getIndexWriter(Workspace.java:180) 
    at org.hibernate.search.backend.impl.lucene.PerDPQueueProcessor.run(PerDPQueueProcessor.java:103) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    at java.lang.Thread.run(Thread.java:662) 
17:11:57,670 ERROR PerDPQueueProcessor:118 - Unexpected error in Lucene Backend: 
org.hibernate.search.SearchException: Unable to remove class myapp.item.domain.Item#4 from index. 
    at org.hibernate.search.backend.impl.lucene.works.DeleteExtWorkDelegate.performWork(DeleteExtWorkDelegate.java:77) 
    at org.hibernate.search.backend.impl.lucene.PerDPQueueProcessor.run(PerDPQueueProcessor.java:106) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    at java.lang.Thread.run(Thread.java:662) 
Caused by: java.lang.NullPointerException 
    at org.hibernate.search.backend.impl.lucene.works.DeleteExtWorkDelegate.performWork(DeleteExtWorkDelegate.java:72) 
    ... 7 more 

:インデックス作成後

@Override 
public void createInitialIndexFromDB() { 
    // get session and set flush mode to manually to control the commit 
    FullTextSession fullTextSession = getFullTextSession(); 
    fullTextSession.setFlushMode(FlushMode.MANUAL); 
    // do not add any data to the object context 
    fullTextSession.setCacheMode(CacheMode.IGNORE); 

    addResultsToIndex(fullTextSession, FETCH_ITEMS_TO_INDEX); 
    addResultsToIndex(fullTextSession, FETCH_DRAFTS_TO_INDEX); 
    addResultsToIndex(fullTextSession, FETCH_RESERVATIONS_TO_INDEX); 
    addResultsToIndex(fullTextSession, FETCH_SALES_TO_INDEX); 

    fullTextSession.flushToIndexes(); 
    fullTextSession.clear(); 
} 

private void addResultsToIndex(FullTextSession fullTextSession, String query) { 
    ScrollableResults results = fullTextSession.createQuery(query).scroll(
      ScrollMode.FORWARD_ONLY); 
    for (int index = 1; results.next(); index++) { 
     fullTextSession.index(results.get(0)); 
     if (index % BATCH_SIZE == 0 || results.isLast()) { 
      fullTextSession.flushToIndexes(); 
      fullTextSession.clear(); 
     } 
    } 
} 

private FullTextSession getFullTextSession() { 
    Session session = this.sessionFactory.getCurrentSession(); 
    return Search.getFullTextSession(session); 
} 

私のインデックスに対するすべての変更は、カスタムFullTextIndexEventListenerを通過している:

public final class HibernateItemEventListener extends 
     FullTextIndexEventListener { 

    private static final Logger log = LoggerFactory 
      .getLogger(HibernateItemEventListener.class); 

    public HibernateItemEventListener() { 
     super(Installation.SINGLE_INSTANCE); 
    } 

    @Override 
    public void onPostInsert(PostInsertEvent event) { 

     log.debug("onPostInsert"); 
     if (!isIndexed(event.getEntity())) 
      return; 

     // Without these checks the elements are added twice to the index! 
     if (event.getEntity() instanceof ItemReservation) 
      return; 

     if (event.getEntity() instanceof ItemSale) 
      return; 

     super.onPostInsert(event); 
    } 

    @Override 
    public void onPostUpdate(PostUpdateEvent event) { 
     log.debug("onPostUpdate - Start"); 
     if (!isIndexed(event.getEntity())) 
      return; 

     Serializable id = event.getId(); 
     log.debug("onPostUpdate - Need update for id " + id); 

     if (used) { 
      boolean identifierRollbackEnabled = event.getSession().getFactory() 
        .getSettings().isIdentifierRollbackEnabled(); 
      final Object entity = event.getEntity(); 
      if (searchFactoryImplementor.getDocumentBuilderIndexedEntity(entity 
        .getClass()) != null 
        || searchFactoryImplementor 
          .getDocumentBuilderContainedEntity(entity 
            .getClass()) != null) { 

       // Remove item 
       if (entity instanceof Item) { 
        Item item = (Item) entity; 
        if (item.getQuantity() < 1) { 
         processWork(entity, id, WorkType.PURGE, event, 
           identifierRollbackEnabled); 
         return; 
        } 
       } 

       // Remove reservation 
       if (entity instanceof ItemReservation) { 
        ItemReservation ir = (ItemReservation) entity; 
        if (ir.getActive() < 1) { 
         processWork(entity, id, WorkType.PURGE, event, 
           identifierRollbackEnabled); 
         return; 
        } 
       } 

       // Update entity 
       processWork(entity, id, WorkType.UPDATE, event, 
         identifierRollbackEnabled); 
      } else { 
       // Add entity 
       processWork(entity, id, WorkType.ADD, event, 
         identifierRollbackEnabled); 
      } 
     } 
    } 

    @Override 
    public void onPostDelete(PostDeleteEvent event) { 
     log.debug("onPostDelete - Start"); 
     if (!isIndexed(event.getEntity())) 
      return; 
     log.debug("onPostDelete - Need delete for id " + event.getId()); 
     super.onPostDelete(event); 
    } 

    private boolean isIndexed(Object entity) { 
     return entity instanceof Item || entity instanceof Draft 
       || entity instanceof ItemReservation 
       || entity instanceof ItemSale; 
    } 
} 

例外は、上記(検索が行うWOアプリケーション自体には影響を与えません。 RK)が、それは時々私は)ロックの問題と関連していると仮定し、他の多くの重要な例外(につながる:

17:11:58,866 ERROR LogErrorHandler:82 - Exception occurred java.io.FileNotFoundException: _iz.fdx 
java.io.FileNotFoundException: _iz.fdx 
    at org.apache.lucene.store.FSDirectory.fileLength(FSDirectory.java:284) 
    at org.apache.lucene.index.SegmentInfo.sizeInBytes(SegmentInfo.java:303) 
    at org.apache.lucene.index.LogMergePolicy.sizeBytes(LogMergePolicy.java:193) 
    at org.apache.lucene.index.LogByteSizeMergePolicy.size(LogByteSizeMergePolicy.java:45) 
    at org.apache.lucene.index.LogMergePolicy.useCompoundFile(LogMergePolicy.java:147) 
    at org.apache.lucene.index.DocumentsWriter.flush(DocumentsWriter.java:593) 
    at org.apache.lucene.index.IndexWriter.doFlush(IndexWriter.java:3587) 
    at org.apache.lucene.index.IndexWriter.prepareCommit(IndexWriter.java:3376) 
    at org.apache.lucene.index.IndexWriter.commitInternal(IndexWriter.java:3485) 
    at org.apache.lucene.index.IndexWriter.commit(IndexWriter.java:3467) 
    at org.apache.lucene.index.IndexWriter.commit(IndexWriter.java:3451) 
    at org.hibernate.search.backend.Workspace.commitIndexWriter(Workspace.java:220) 
    at org.hibernate.search.backend.impl.lucene.PerDPQueueProcessor.run(PerDPQueueProcessor.java:109) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    at java.lang.Thread.run(Thread.java:662) 
17:11:59,991 ERROR LogErrorHandler:82 - Exception occurred java.io.FileNotFoundException: /opt/myapp/item_index/myapp.item.domain.Item/_iz.cfs (No such file or directory) 

任意のヒントを?

EDIT:ライブラリーの調整とJMeterの攻撃性の増加(複数のスレッド)の後 例外とインデックス破損がまだ表示されます。

12:08:11,163 ERROR LogErrorHandler:82 - Exception occurred java.io.FileNotFoundException: /opt/myapp/item_index/myapp.item.domain.Item/_8gy.cfs (No such file or directory) 
Primary Failure: 
    Entity myapp.item.domain.Item Id 596 Work Type org.hibernate.search.backend.DeleteLuceneWork 
Subsequent failures: 
    Entity myapp.item.domain.Item Id 596 Work Type org.hibernate.search.backend.AddLuceneWork 
    Entity myapp.item.domain.Item Id 734 Work Type org.hibernate.search.backend.DeleteLuceneWork 
    Entity myapp.item.domain.Item Id 734 Work Type org.hibernate.search.backend.AddLuceneWork 
    Entity myapp.item.domain.Item Id 599 Work Type org.hibernate.search.backend.DeleteLuceneWork 
    Entity myapp.item.domain.Item Id 599 Work Type org.hibernate.search.backend.AddLuceneWork 
    Entity myapp.item.domain.Item Id 735 Work Type org.hibernate.search.backend.DeleteLuceneWork 
    Entity myapp.item.domain.Item Id 735 Work Type org.hibernate.search.backend.AddLuceneWork 
    Entity myapp.item.domain.Item Id 598 Work Type org.hibernate.search.backend.DeleteLuceneWork 
    Entity myapp.item.domain.Item Id 598 Work Type org.hibernate.search.backend.AddLuceneWork 
    Entity myapp.item.domain.Item Id 720 Work Type org.hibernate.search.backend.DeleteLuceneWork 
    Entity myapp.item.domain.Item Id 720 Work Type org.hibernate.search.backend.AddLuceneWork 

java.io.FileNotFoundException: /opt/myapp/item_index/myapp.item.domain.Item/_8gy.cfs (No such file or directory) 
    at java.io.RandomAccessFile.open(Native Method) 
    at java.io.RandomAccessFile.<init>(RandomAccessFile.java:216) 
    at org.apache.lucene.store.SimpleFSDirectory$SimpleFSIndexInput$Descriptor.<init>(SimpleFSDirectory.java:69) 
    at org.apache.lucene.store.SimpleFSDirectory$SimpleFSIndexInput.<init>(SimpleFSDirectory.java:90) 
    at org.apache.lucene.store.NIOFSDirectory$NIOFSIndexInput.<init>(NIOFSDirectory.java:91) 
    at org.apache.lucene.store.NIOFSDirectory.openInput(NIOFSDirectory.java:78) 
    at org.apache.lucene.index.CompoundFileReader.<init>(CompoundFileReader.java:66) 
    at org.apache.lucene.index.CompoundFileReader.<init>(CompoundFileReader.java:55) 
    at org.apache.lucene.index.IndexWriter.getFieldInfos(IndexWriter.java:1193) 
    at org.apache.lucene.index.IndexWriter.getCurrentFieldInfos(IndexWriter.java:1213) 
    at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:1149) 
    at org.hibernate.search.backend.Workspace.createNewIndexWriter(Workspace.java:202) 
    at org.hibernate.search.backend.Workspace.getIndexWriter(Workspace.java:180) 
    at org.hibernate.search.backend.impl.lucene.PerDPQueueProcessor.run(PerDPQueueProcessor.java:103) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    at java.lang.Thread.run(Thread.java:662) 
12:08:11,163 ERROR PerDPQueueProcessor:118 - Unexpected error in Lucene Backend: 
org.hibernate.search.SearchException: Unable to remove class myapp.item.domain.Item#596 from index. 
    at org.hibernate.search.backend.impl.lucene.works.DeleteExtWorkDelegate.performWork(DeleteExtWorkDelegate.java:77) 
    at org.hibernate.search.backend.impl.lucene.PerDPQueueProcessor.run(PerDPQueueProcessor.java:106) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    at java.lang.Thread.run(Thread.java:662) 
Caused by: java.lang.NullPointerException 

EDITをデバッグした後: するFileNotFound(したがって、IndexWriter NPE)を生成Workspace.createNewIndexWriter()メソッドの

IndexWriter writer = new IndexWriter(directoryProvider.getDirectory(), writerConfig); 

にあります。 Hibernateの検索は非常にLuceneのAPIの変更に連結されている

writerConfig: 
matchVersion=LUCENE_31 
analyzer=org.apache.lucene.analysis.SimpleAnalyzer 
delPolicy=org.apache.lucene.index.KeepOnlyLastCommitDeletionPolicy 
commit=null 
openMode=CREATE_OR_APPEND 
similarity=org.apache.lucene.search.DefaultSimilarity 
termIndexInterval=128 
mergeScheduler=org.hibernate.search.backend.impl.lucene.overrides.ConcurrentMergeScheduler 
default WRITE_LOCK_TIMEOUT=1000 
writeLockTimeout=1000 
maxBufferedDeleteTerms=-1 
ramBufferSizeMB=16.0 
maxBufferedDocs=-1 
mergedSegmentWarmer=null 
mergePolicy=[LogByteSizeMergePolicy: minMergeSize=1677721, mergeFactor=10, maxMergeSize=2147483648, maxMergeSizeForOptimize=9223372036854775807, calibrateSizeByDeletes=true, maxMergeDocs=2147483647, useCompoundFile=true] 
maxThreadStates=8 
readerPooling=false 
readerTermsIndexDivisor=1 
+0

インデックスはどのようなファイルシステムに保存されていますか?それは信頼できるのですか?また、カスタムFullTextIndexEventListenerの間違いが疑われるNullPointerExceptionがあります。このカスタムリスナーが必要なものを要約できますか? – Sanne

+0

私はxubuntuとCentOSでext4ファイルシステムを使用しています(2つの異なるシステムで試しました)。インデックスファイルはTomcatと同じサーバー上にあり、ファイルのアクセス権は正しく割り当てられています。カスタムリスナーを使用して、索引から(つまり検索結果から)使用不可能な項目(量<1)が削除されますが、それらはデータベースに保持されます。リスナーのコードに何か間違っていますか? – Wizche

+0

私はあなたの聴取者には何も見当たりませんでしたが、まずNullPointerExceptionをデバッグするべきだと思います。ファイルロックの問題を引き起こすクリティカルパスでインデックスキューを強制終了していると思われます。 NPEはリスナーの何かに起因する可能性があると思います。 – Sanne

答えて

1

hibernate search forum thread

から、私はそれを解決したと思います。

問題は休止検索そのものではなかった、それは、並行トランザクションのしきい値が が(おそらく、オープンファイル記述子を残して)超過した後 はスレッドを殺したAtomikosました。私は 同時トランザクション制限(50だった)を増やし、問題はなくなりました。

これにもかかわらず、私はまだluceneクエリを実行するたびに、休止状態の検索がインデックスの作成者 を開いていることを理解できません。

1

は、あなたが使用しているLuceneのバージョンは、Hibernateの検索3.4.2の開発中に使用したものとは全く異なります。

これらの推奨バージョンです、私はthe pom.xml from the 3.4.2.Final tagからそれらを読んでいる:

<hibernate.search.version>3.4.2.Final</hibernate.search.version> 
<apache.lucene.version>3.1.0</apache.lucene.version> 
<apache.solr.version>3.1.0</apache.solr.version> 
<hibernate.version>3.6.10.Final</hibernate.version> 
+0

Sanne、私はJMeterスレッド/要求パラメータを増やそうとしました。例外は依然として約1000件の要求の後に来ている。上記の私の編集を参照してください。私は、Hibernate Search 3.4.2 pomファイルに記述されているとおりにライブラリを修正しました。 – Wizche