专门的作家流程,只有读者在另一个过程中

时间:2014-05-12 09:05:22

标签: c# .net asp.net-mvc lucene.net

我正在开发一个使用Lucene.net实现全文搜索的ASP.Net MVC 5应用程序。

由于ASP {Net中有potentional problems托管后台任务,我正在思考以下场景是否可行:

  1. 将唯一的Lucene编写器移动到一个专用进程,该进程定期检查数据库中是否有未编入索引的行并相应地更新lucene索引
  2. 将读者留在ASP.NET工作进程中
  3. 根本不使用FSDirectory吗?

2 个答案:

答案 0 :(得分:0)

我认为这是可能的。您可以同时拥有多个IndexReader,它应该没问题,甚至还有一个外部锁定功能(基于文件系统),用于多进程锁定。

请记住,IndexReader将搜索当前的"快照"从创建时开始,你应该找到一种方法来转储"转储"索引更改时的IndexReaders。您当然可以为每次搜索创建一个IndexReader,但这可能不建议使用,如果您当前正在写入索引,则会失败。出于这些目的,你可以从当前作者中检索一个阅读器,但这不是一个选项,因为它们将驻留在不同的进程中。

您可能会发现这篇文章很有趣:

http://devlearnings.wordpress.com/2010/04/26/lucene-reuse-indexsearcher-rather-creating-new-everytime/

答案 1 :(得分:0)

在我为该项目编写的一个小助手类的帮助下,我设法让这个工作得很好。下面的工厂类共享一个具有任意数量线程的indexReader,并确保从GetCurrentReader()返回的读取器与索引的状态保持同步。

class IndexReaderFactory :
  IDisposable
{
  public IndexReaderFactory(bool isReadonly)
  {
    this.isReadonly = isReadonly;
  }

  IndexReader reader;
  readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
  private readonly bool isReadonly;

  /// <summary>
  /// Returns a reader that isCurrent
  /// </summary>
  public IndexReader GetUpToDateReader()
  {
    rwl.EnterUpgradeableReadLock();

    try
    {
      if (reader == null)
      {
        rwl.EnterWriteLock();

        try
        {
          if (logger.IsInfoEnabled)
            logger.Info("Creating IndexReader on directory {0}", AppSettingsBase.LucenePostIndexLocation);

          reader = IndexReader.Open(FSDirectory.Open(AppSettingsBase.LucenePostIndexLocation), isReadonly);
        }

        finally
        {
          rwl.ExitWriteLock();
        }
      }

      else if(!reader.IsCurrent())
      {
        rwl.EnterWriteLock();

        try
        {
          if (logger.IsInfoEnabled)
            logger.Info("IndexReader is not current. Re-opening");

          reader = reader.Reopen();
        }

        finally
        {
          rwl.ExitWriteLock();
        }
      }
    }

    finally 
    {
      rwl.ExitUpgradeableReadLock();
    }

    return reader;
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  public void Dispose(bool disposing)
  {
    if (disposing)
    {
      // get rid of managed resources
    }

    if(reader != null)
      reader.Dispose();
  }
}