Mtail导致Nginx报警延迟
问题描述
原因分析
优化重构
业界关于Nginx监控的主流的监控方案主要有以下三类:
远端处理日志:基于filebeat、logstash之类的日志采集器将nginx日志传输到kafka里,然后使用流式计算任务(flink、storm、spark等)实时消费进行统计。
优点:kafka、filebeat、flink都是比较成熟的组件,系统搭建比较简单。
缺点:数据传输链路过长、外部依赖太多,稳定性相对较差。
本地处理日志:Agent在nginx机器上进行日志解析、计算,然后通过主动上报或开放一个采集端口由采集端拉取两种方式上报到监控中心。
优点:没有日志传输,也不依赖外部系统,而且由于Nginx机器本身负载也不高,因此可以分出一部分算力给Agent使用,相比方案一可以节省相当一部分后端计算资源。
缺点:没有资源限制功能,如果资源消耗较高可能会影响到Nginx。
基于插件、lua脚本之类的监控增强:常见的有 nginx-module-vts、falcon-ngx_metric之类,可以将Nginx内部状态进行导出,可以配合Open-falcon或Prometheus之类的开源监控。
优点:由于可以直接使用Nginx内部变量,因此不需要解析日志,性能最好。
缺点:需要重新编译Nginx后才可启用,对nginx的侵入性较大,一旦依赖出现问题对Nginx将是破坏性的影响;另外部署和更新的成本也较高。
出现问题
随着新Nginx监控架构的推进, Mtail的一些问题也逐渐显露了出来。事情就发生在一个普通的周四晚上,白天的时候配合sa灰度了公司一个较大的域名所属的Nginx集群20台左右机器,Mtail进程的cpu大概维持在60%~70%之间、内存在60m左右,性能也还符合预期。结果晚上下班回家洗完手刚准备拿起玩具逗娃,刷刷刷刷4条Mtail性能报警毫无防备的打乱了我逗娃的节奏,赶紧打开报警机器对应的域名数据一看,监控图线断的简直是惨不忍睹:
登上Nginx机器发现进程的cpu使用率保持在130%左右,偶尔还会达到150%,对比白天的时候翻了一倍。同批部署的其他机器的上报数据虽然没有出现断线,但是cpu也接近110%。查看Mtail监控日志,cpu上涨的时间和业务晚高峰时间一致,看起来像是晚高峰日志量增加导致Mtail出现了性能问题。可是根据之前的压测记录,Mtail一分钟可以处理100万日志,该批机器晚高峰日志量也就50~60万/分钟左右,按道理说不应该出现这种情况啊。
继续对比白天和晚上的监控结果,发现晚高峰的时候Mtail的监控对象个数翻了一倍,因为之前压测的时候着重关注了日志量这个指标,对于监控对象个数只是模拟了一个很简单的场景,难道是Mtail的处理性能不只是取决于日志量,还跟监控对象个数有很大关系? 赶紧在隔离环境的机器上使用脚本模拟了60万条线上机器的日志,重新测试后发现原本跑完60万压测日志都花不到30秒的Mtail,换成线上的日志后需要跑近3分钟!
妥妥的性能问题,没别的说的赶紧解决吧。首先比较容易想到的就是从程序启动参数上进行优化,可是go不像java那样有丰富的启动参数(有不对的地方请评论区指正),在网上搜到一些参数设置了也是没啥效果。尝试用master分支的代码 build 了下,结果还是将近3分钟,在测试误差范围以内。在Mtail的github的仓库里翻了翻issue列表,最近一次提的性能相关的issue还是17年的。。。
没别的好办法只能自己上了,尝试着使用Go自带的性能分析工具 pprof 生成一下最近60秒运行的报告,执行top10 命令,发现其中一个Mtail的方法的耗时比较可疑,根据方法名字看应该是和查找监控对象相关的,累计调用耗时占到了50%多,很有可能是晚高峰监控对象增多而该方法执行效率不太高最终出现性能问题了。
为了印证想法从git上把Mtail的源码拉下来简单扫了几眼,不得不说Google开源的项目结构还是很工整的,代码的模块化做的很好,比较容易的就理清了程序的运行逻辑,很典型的生产者消费者模型。在定位到相关代码后我更加坚信了自己的想法:果然是写出了个 O(M*N)复杂度的查询!!!按照它的实现逻辑,查找性能是与监控对象个数和监控对象维度成反比的,如果晚高峰监控对象比白天的时候多一倍,那么查询性能就弱一倍!
大晚上提issure等官方修复肯定是来不及了,还好go的语法比较简单,虽然没有开发go的经验也能凭着搜索引擎写写。核心优化的原理就是为每个监控对象计算一个唯一key,使用 map 存储key和监控对象的映射,这样查找的时间复杂度就和监控对象个数没有太大关系了。在通过单元测试后,赶紧把代码打包放到测试环境试了一下,跑同一份线上的日志数据,只花了不到30秒, 性能提升了足足5倍,反复核对了几遍数据准确性也没有问题。
小插曲
反思
🔍
🕵️♀️
有 趣 灵 魂 集 结 地
@BUG侦探