C# 在另一个进程中只有读卡器的专用编写器进程
我正在开发一个ASP.NETMVC5应用程序,它使用Lucene.Net实现全文搜索 由于在ASP.Net中托管后台任务的复杂性,我正在考虑以下场景是否可行:C# 在另一个进程中只有读卡器的专用编写器进程,c#,.net,asp.net-mvc,lucene.net,C#,.net,Asp.net Mvc,Lucene.net,我正在开发一个ASP.NETMVC5应用程序,它使用Lucene.Net实现全文搜索 由于在ASP.Net中托管后台任务的复杂性,我正在考虑以下场景是否可行: 将唯一的Lucene编写器移动到一个专用进程,该进程定期检查数据库中未索引的行,并相应地更新Lucene索引 将读卡器保留在ASP.NET工作进程中 使用FSDirectory可以吗?我认为这是可能的。您可以同时拥有多个IndexReader,这应该没问题,它甚至还具有用于多进程锁定的外部锁定功能(基于文件系统) 请记住,IndexRea
使用FSDirectory可以吗?我认为这是可能的。您可以同时拥有多个IndexReader,这应该没问题,它甚至还具有用于多进程锁定的外部锁定功能(基于文件系统) 请记住,IndexReader将从创建时开始在当前“快照”中搜索,因此您应该找到在索引更改时“转储”IndexReader的方法。当然,您可以为每个搜索创建一个IndexReader,但这可能不是推荐的做法,如果您当前正在写入索引,则可能会失败。出于这些目的,您可以从当前编写器检索读取器,但这不是您的选项,因为它们将驻留在不同的进程中 您可能会发现这篇文章也很有趣:
在我为项目编写的一个小助手类的帮助下,我成功地使它正常工作。下面的工厂类与任意数量的线程共享一个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();
}
}
class IndexReaderFactory:
可识别
{
public IndexReaderFactory(bool为只读)
{
this.isReadonly=isReadonly;
}
索引阅读器;
readonly ReaderWriterLockSlim rwl=新的ReaderWriterLockSlim();
私有只读bool为只读;
///
///返回当前的读取器
///
公共索引阅读器GetUpToDateReader()
{
rwl.EnterUpgradeableReadLock();
尝试
{
如果(读卡器==null)
{
rwl.EnterWriteLock();
尝试
{
如果(logger.IsInfo已启用)
Info(“在目录{0}上创建IndexReader”,AppSettingsBase.LucenePostIndexLocation);
reader=IndexReader.Open(FSDirectory.Open(appsetingsbase.LucenePostIndexLocation),isReadonly);
}
最后
{
rwl.ExitWriteLock();
}
}
如果(!reader.IsCurrent())
{
rwl.EnterWriteLock();
尝试
{
如果(logger.IsInfo已启用)
logger.Info(“IndexReader不是当前的。正在重新打开”);
reader=reader.Reopen();
}
最后
{
rwl.ExitWriteLock();
}
}
}
最后
{
rwl.ExitUpgradeableReadLock();
}
返回读取器;
}
公共空间处置()
{
处置(真实);
总干事(本);
}
公共无效处置(bool处置)
{
如果(处置)
{
//摆脱托管资源
}
if(读卡器!=null)
reader.Dispose();
}
}
如果当前已写入索引,为什么您认为打开读卡器会失败?@OliverWeichhold好吧,也许不会失败,但您可能会最终处于读卡器没有索引或不一致的状态。我真的不记得锁是如何影响读者的。