背景介绍
首先介绍下项目ES集群环境:5台server组成的ES集群,每台server物理内存64G还有几个G的SWAP,其中给ES分配40G的堆内存;除ES之外,server上还跑着一些其他service.
项目内使用ES,主要存储fluentD泵过来的k8s集群内所有app的系统log,之外还维护GEO app的业务数据.
事件还原
期初ES只是偶尔单个节点报OOM,并没有引起足够的重视,特别是GEO team 重启ES节点即可解决问题.
但随着GEO业务数据量的增大,OOM越来越频繁,整个ES集群crash掉,才开始引起重视.
尝试解决
遇到OOM,第一时间想到去看ES JDK的配置,看到虽然有dump但是由于dump文件太大,无法在线分析,也无法download或者scp到其他机器上,影响了定位问题最直接的方式.
遂查看linux server /log, 每次在service OOM的时候,都会记录最后的JDK堆栈使用情况,已经process被谁已经何时被kill的log.
发现ES堆+SWAP竟然还有剩余,但有意思的是server本身内存不足,并触发保护机制主动kill掉最占用内存的process,即kill es.
问题分析
是什么挤压到了server的内存使用呢? 在确定了server上其他几个service的内存使用情况后,排除了其他service的嫌疑.
同时定位到OOM发生的trigger是GEO业务数据的大query.
也就是说,ES有大query的时候,会挤压到系统内存,而非JDK堆内存..
莫非ES的query会使用堆外内存?
在查看了ES的文档验证了这个想法. give (less than) half your memory to Lucene 原来是Lucene! ES使用Lucene做检索,而Lucene竟然使用的是堆外内存,这点确实没考虑到..
问题解决
在确定OOM是由Lucene使用堆外内存引起的之后,将ES分配的内存从40G降到32G,留给Lucene更充足的内存,同时优化GEO query,问题得到解决.