一,问题描述

druid router界面显示historical服务不正常,Datasource0%可用,druid历史数据不可查。historical节点日志显示一直在loading segment,但是loading结束后可能会报错segment文件格式错误,如下图,报错的文件路径本地可能没有但是hdfs上文件没问题。报错后过一会儿又开始重新开始loading过程,如此往复循环。

dubbo 内存溢出 druid 内存溢出_加载segment报错


druid目录下有进程崩溃的日志。

dubbo 内存溢出 druid 内存溢出_historical死循环_02

二,问题原因

查看hs_err_pid文件可知historical进程死掉的原因是内存溢出。

dubbo 内存溢出 druid 内存溢出_historical死循环_03


historical在加载文件的时候内存溢出死掉了,druid 自带的supervise会重新启动historical进程,然后重新loading segments,然后又死掉又loading segments。。。

使用free -h 命令查看内存,我们的服务器还有一半的物理内存空闲,为什么druid会内存溢出?答案是内存映射文件。

内存映射文件(Memory-mapped file)
或称“文件映射”、“映射文件”,是一段虚内存逐字节对应于一个文件或类文件的资源,使得应用程序处理映射部分如同访问主内存。内存映射文件能让你创建和修改那些大到无法读入内存的文件。有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问了。将文件的一段区域映射到内存中,比传统的文件处理速度要快很多
虚拟内存:
是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上物理内存通常被分隔成多个内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术使得大型程序的编写变得更容易,对真正的物理内存(例如RAM)的使用也更有效率。此外,虚拟内存技术可以使多个进程共享同一个运行库,并通过分割不同进程的内存空间来提高系统的安全性。

查看druid官网,historical进程使用内存映射文件来处理segment信息,但是操作系统会限制进程申请**内存映射文件(Memory-mapped file)**的资源数量。

dubbo 内存溢出 druid 内存溢出_dubbo 内存溢出_04

三,解决办法

1,调大Linux max_map_count参数。

vim /etc/sysctl.conf
#修改vm.max_map_count 的值默认为65530,
vm.max_map_count=655300

让配置生效

sysctl -p

2,内存映射文件(Memory-mapped file) 的分配是以area为单位的,大量的小文件会导致大量的碎片空间无法使用,所以应该避免segment过小的情况,官方建议每个segment文件大小在300MB-700MB范围内或者每个segment文件包含的数据条数为500万条。流失数据摄入的情况下比如kafka,一定要开启Datasource segemnt自动合并。