lucene在NFS的环境中搜索导致JVM崩溃

布谷鸟 发布于 2017/11/05 13:53
阅读 423
收藏 0

我们使用了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
红薯
红薯

读取的问题不大啊,写的话只能有一个,不会有什么问题啊

0
布谷鸟
布谷鸟

引用来自“红薯”的评论

读取的问题不大啊,写的话只能有一个,不会有什么问题啊

我的确是用一个线程在写,3台tomcat只读,也在写索引的服务中配置了删除策略,版本是 lucene 5.5,仍然导致jvm崩溃。

倘若我把JOB服务器上的增量更新索引的线程停掉,其它的3台机器长时间跑都不会有问题,但这样显然不行,新数据不能够及时被搜索出来,对业务影响还是比较大的。可一旦开启增量写索引的线程,运行最多一天,就会在搜索的时候报错,随即jvm崩溃掉。

之前单独一台服务器没用NFS的时候,服务一直是稳定的。

0
布谷鸟
布谷鸟

引用来自“红薯”的评论

读取的问题不大啊,写的话只能有一个,不会有什么问题啊

这是我应用删除策略的类

/**
 * 基于nfs文件系统的索引删除策略
 * 
 * @author cq
 *
 */
public class NFSIndexDeletionPolicy extends IndexDeletionPolicy {

	private List<IndexCommit> hangQueue = new ArrayList<IndexCommit>();

	@Override
	public void onInit(List<? extends IndexCommit> commits) throws IOException {
		// TODO Auto-generated method stub
		onCommit(commits);
	}

	@Override
	public void onCommit(List<? extends IndexCommit> commits) throws IOException {
		// TODO Auto-generated method stub
		// 向集合中填充
		this.hangQueue.addAll(commits);
		// 获取当前时间
		int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
		int minute = Calendar.getInstance().get(Calendar.MINUTE);
		// 偶数小时更新,并避免在临界时间操作,相应的,只允许在奇数小时刷新IndexReader
		if ((hour % 2 == 0) && (minute < 50) && (minute > 10)) {
			int size = this.hangQueue.size();
			for (int i = 0; i < size - 1; i++) {
				this.hangQueue.get(i).delete();
			}
			// 清空队列
			this.hangQueue.clear();
		}
	}
}

 

0
红薯
红薯
这个错误应该还是在操作索引时被中断吧,索引的写改删都应该在独立进城,最好不要放tomcat
0
布谷鸟
布谷鸟

引用来自“红薯”的评论

这个错误应该还是在操作索引时被中断吧,索引的写改删都应该在独立进城,最好不要放tomcat

索引的改写删放在JOB上,我能够确保其是独立的,并且写操作也没有任何问题。现在就是读取的过程中遇到麻烦,我也认为是搜索读索引的时候,索引文件发生了变化,随即报错崩溃,但不知道造成这种现象的原因到底在哪儿,或者应该如何避免。

我尝试了索引构建线程和SearcherManager.maybeRefresh()按时间交叉执行确保其不重叠,问题依旧。

能google出一些相似的国内国外的帖子,有不少回复不建议lucene使用NFS,可是阿里云的NAS服务太好用了,成本也非常低,还是更寄希望把问题解决,没有换方案的打算。

红薯
红薯
我们放nfs毫无压力,你读得很厉害吗
0
布谷鸟
布谷鸟

引用来自“红薯”的评论

这个错误应该还是在操作索引时被中断吧,索引的写改删都应该在独立进城,最好不要放tomcat

那可能就是我配置,或者哪里的策略不对。
读取的不频繁,早晚高峰也就平均每分钟也就百十来次搜索,但我能够肯定不是并发高的原因。
每个tomat通常都是运行八九个小时,最多十来个小时,通过日志能够发现,这时候搜索可能会报我贴图上的异常:
(Caused by: java.lang.InternalError: a fault occurred in a recent unsafe memory ac)
然后tomcat直接carsh掉,SLB发短信给我监控警报, 我就得披着衣服起床再次启动tomcat了

希望老大有时间能够讲讲osc使用luceue基于NFS共享索引的时候对策略和NFS配置做的一些调整,可能很多人习以为常的操作,我这些新手不曾了解,就裁坑里了。

我先去发个悬赏

布谷鸟
布谷鸟
回复 @红薯 : 共享索引之后,IndexDeletionPolicy 一定需要做修改吧?相应的IndexReader管理也需要调整吧,老大您是怎么做的有时间说一下不,我有些怀疑我自己的类写的不对,但网上找不到参考例子
红薯
红薯
没有任何特殊的啊,真没有
0
t
type-moon
job试试能不能samba挂载。或iscsi映射
0
ArcticMosquito
ArcticMosquito

未找到具体原因之前,为了避免半夜起床,可以定时轮流重启三个tomcat.....

0
a
azureplus
用tomcat demo方式启动 挂不了
0
刘少
刘少

我用rsync进行索引文件的分发,当commit完成后,再进行分发, 你这种状况的话,建议: 

job服务器写索引到本地目录, commit后,拷贝到nfs的目录,避免中间状态, 其他没有特殊.

返回顶部
顶部