本篇文章阅读时间大约2分钟
最近公司生产环境服务器经常内存报警,而且多发生在凌晨,见下图。

由于一直报警,因此写了一个内存监控的脚本,见上篇文章。最终发现是由于filebeat导致,怀疑是由于json相关配置导致,然而发现并非如此。那我们书接前文。
查了下网上关于filebeat内存暴增的资料,发现这样一篇文章:filebeat 实践 - 内存占用 - 最大内存占用.
文章阐述了filebeat内存暴增的原因,内存公式为:
$$ bytes_each_log * spool_size * M + a * N $$
bytes_each_log是指单条日志大小,spool_size是配置文件里的配置项,M是单条日志在内存里的溢价系数(> 1),N表示采集文件的个数,a为常数
spool_size的默认值是2048,我们的配置文件里也没设置。具体比照见下表:

因此如果有单条日志过大的情况,内存会突增。所以要设置合适的spool_size值,建议是128或者256.
你以为这样就结束了吗,我们还要深挖原因,为什么会有单条过大的日志。这个服务平时压力并不大,日志量也很小,不应该出现这种情况。我们查找日志发现有很多二进制字符,如下图:

日志文件是stdout.log,这个文件是记录程序执行的所有控制台输出,命令如下:
nohup java ${JAVA_OPTS} -cp ${CLASS_PATH} -jar ${DEFAULT_JAR} --spring.profiles.active=${SERVER_ENVIROMENT} ${APP_NAME}-app >$LOG_PATH/stdout.log 2>&1 &
由于担心时间长文件无限制增长,就定了个计划任务,每隔两天清空文件,命令如下:
# clean stdout log
20 02 */2 * * echo "" > /data0/logs/xxxx/stdout.log
正常情况下程序不会输出这样的内容。而且用file命令看文件已经变为了二进制文件,并未文本文件。如下图:

我们继续检查为什么会出现这种情况,怀疑是由于 echo 清理导致,这时网上发现如下资料:Oh!MongoDB 日志从文本穿越成了图片?咋整! 里面的碰到的情况跟我们类似,文件变为 PCX ver. 2.5 image data
。文章提到:
- 使用
echo > log
时,会往文件头部插入\n
即16进制的0a
- 在程序正常运行时,log文件是加了锁的,因此强制执行
echo > log
是无法覆盖的,会将所有数据置为0
- 因此文件头部变成了无数的空白
那么如何解决呢,暂时没找到好办法,除非应用重启切割日志,好在这个日志只是控制台输出,其他日志中也包含其内容。
来源:oschina
链接:https://my.oschina.net/u/11638/blog/3047200