解决lucene在NFS的环境中搜索导致JVM崩溃的问题

布谷鸟 发布于 2017/11/05 16:49
阅读 33
收藏 0

我对luceue和NFS了解不够导致线上的项目出现了这种情况。希望热心的朋友能够为我提供可以解决问题的方法。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

luceue 版本:5.5

osc问题在这里:https://www.oschina.net/question/224858_2269172

我们使用了3台服务器部署了tomcat,使用阿里云的SLB做了负载均衡。

至于索引的构建,添加另外使用了一台JOB服务器,定时向挂载的NFS盘commit,这里用的也是阿里云NAS服务,以NFS协议挂载。3台应用服务器以只读模式挂载NFS磁盘,用于响应搜索请求。配置看上去已经完成了,只需要根据特性在代码上做些调整。

  1. 我使用了lucene提供的搜索器管理类(SearcherManager)用于近时搜索,定期调用SearcherManager.maybeRefresh()方法检测索引的更新状态尝试获取更新后的IndexReader。在没有使用NFS的服务之前,服务状态一直良好。
  2. 由于NFS服务本身的限制,文件删除状态不能够被挂载机器及时的检测到,lucene官方文档建议在这种环境下使用自定义索引删除策略(IndexDeletionPolicy)来确保服务能够正常进行。
  3. 于是,我自定义了索引删除策略(IndexDeletionPolicy)在lucene初始化的时候进行配置(IndexWriterConfig),确保索引删除(IndexComment.delete())的时间和检测刷新尝试获取新读取器的过程(SearcherManager.maybeRefresh())不可能重叠。
  4. 部署运行之后,能够发现,调用SearcherManager.maybeRefresh()方法的过程中,segment文件FileNotFoundException异常已经不再出现,说明产生的效果,但原本的关键问题并没有解决。

此异常直接导致jvm崩溃

@红薯  老大,osc现在luceue搜索仍然使用的是NFS做的索引共享么?希望能够给我些建议。刚才看到几年前的帖:
https://www.oschina.net/question/12_2137731
这两天我们的几台tomcat也是CPU跑高,也让我不得不怀疑是NFS的锅,因为相同的环境,没有挂载NFS的服务器一直没有任何异常。

连续几天半夜被报警短信催起床启动已经崩溃的服务,真是折磨!

希望有经验的朋友能够为小弟提供些建议,帮助我解决这个问题,感激不尽!

加载中
0
cole_yang
cole_yang
增加内存即可。因为使用了nfs,文件映射载入到内存中需要更大的内存。给你省了1000元。
0
cole_yang
cole_yang
你使用了nfs,且多个机器同时访问同一个nfs存储,读写并存,很容易出现问题。不建议nfs+lucene的配合。看你的需求,需要3个tomcat进行负载均衡,但是存储通过nfs共享。瓶颈实际上就是在nfs上,毕竟nfs是通过网络访问的。你可以在3个tomcat服务器上都运行完整的程序,索引更新的时候,同时在3个tomcat上更新。这样可以使用本地存储,性能高和没有各种问题。
0
javadeveloper
javadeveloper
建议你还是使用目前比较成熟的产品,比如ES、solr之类的,也不复杂,已经久经考验了,基本上各种场景都被使用并修正bug,用着放心。
0
布谷鸟
布谷鸟
@cole_yang 你好, 我能够确保写是独立的线程,并且3个读取索引的tomcat对NFS成功的应用了只读的权限,我更怀疑是IndexReader/IndexWriter更新策略没有处理好,但对实现机制不清楚,文档看了又看多是对其描述不理解,自然也找不到问题所在了。 另外,如果我关闭了JOB机器上增量更新索引的线程,就不会出现崩溃的问题,可以断定就不是内存的原因,毕竟我只使用了NIOFSDirectory或者MMapDirectory(在linux环境64位jdk下),从来没有用过RAMDirectory,内存溢出应该也会显更加具体的错误信息。 我也想过使用一些系统组件为3台机器同步索引文件,可是这对我又是另外一个难题。 感谢你的回复!
0
布谷鸟
布谷鸟
@javadeveloper 你好,目前没有换方案的计划,最坏的打算,实在解决不了我就把搜索请求全转发到一台机器上。感谢你的回复!
0
javadeveloper
javadeveloper

引用来自“布谷鸟”的评论

@cole_yang 你好, 我能够确保写是独立的线程,并且3个读取索引的tomcat对NFS成功的应用了只读的权限,我更怀疑是IndexReader/IndexWriter更新策略没有处理好,但对实现机制不清楚,文档看了又看多是对其描述不理解,自然也找不到问题所在了。 另外,如果我关闭了JOB机器上增量更新索引的线程,就不会出现崩溃的问题,可以断定就不是内存的原因,毕竟我只使用了NIOFSDirectory或者MMapDirectory(在linux环境64位jdk下),从来没有用过RAMDirectory,内存溢出应该也会显更加具体的错误信息。 我也想过使用一些系统组件为3台机器同步索引文件,可是这对我又是另外一个难题。 感谢你的回复!
更大的可能是索引程序内部在自己合并操作时,你的程序作了更新操作导致内存操作问题。在ES出来之前我也写过一个自动化增量更新索引并提供搜索的程序,不过只是一个实例,现网运行一年多没有发现你说的这个问题。
0
cole_yang
cole_yang
MMapDirectory就是使用内存文件。多线程只是对同一个进程有效。你有3个tomcat在不同的机器上,和线程没有任何关系了。你想在一个进程上使用线程去同步其它进程是不可能的。如果是本地文件,lucene可以使用文件锁,但是nfs不行。而且回到前面的问题,如果不想换方案,就加大内存。MMapDirectory是使用内存的。
0
cole_yang
cole_yang
实际上你原来的设计就不是很妥。如果没有非常特别的原因。不要多个进程同时对同一个存储进行操作,很容易出现问题。您3个tomcat服务器同时访问同一个nfs存储,本身就很容易出现问题。很容易出现读写冲突。
0
布谷鸟
布谷鸟
@cole_yang 你好,目前为止,我使用的是NIOFSDirectory,问题是依旧的。3台tomcat的机器对NFS挂载的磁盘只有读操作且只有读权限,只有JOB机器才有写权限,我不太明白,并发读也要考虑锁么? 感谢你的回复!
0
cole_yang
cole_yang
NIOFSDirectory的性能很差。job去写的时候,其它tomcat有可能正在读。因为不是本地文件,且不同服务器进程访问。使用文件锁没有作用。
返回顶部
顶部