内存减少 60%,OpenResty XRay 精准定位问题代码,快速完成修复上线
我们业务大规模的使用 OpenResty 相关生态,业务中偶尔出现过一些比较诡异的难以定位的问题, 比如内存、CPU 热点等,借助于 OpenResty XRay,我们能很快定位到根因并迅速解决这些问题。
OpenResty XRay部署简单,对业务无侵入性,界面直观清晰,对我们提供了很多优化的方向性指引, 已经成为我们的有力武器。
祝 OpenResty XRay 越来越好!
OpenResty XRay 是由 OpenResty Inc.1 研发的深度应用性能管理(APM)产品,以非侵入式的方式,对应用系统进行实时 X 光诊断与优化。今年上半年公开申请试用以来,已经成功的帮助到了不少的客户,得到了客户的广泛好评。
上海云盾信息技术有限公司(YUNDUN),是专注于提供新一代安全产品和服务的创新创业企业。 在云盾的产品线中,也有大规模使用开源 OpenResty,开源 OpenResty 的高性能以及灵活的定制能力,为云盾的产品提供了强大的支持。同时,在使用开源 OpenResty 的过程中,也碰到了一些比较棘手的问题。
worker 进程内存占用高
这是云盾第一次使用 XRay 的场景,当时生产环境的 OpenResty worker 进程占用的内存比预期的多,并且把流量切走之后内存也不会下降。当时排查了很久,初步定位是 LuaJIT 占用内存多导致的,但是没有办法定位到更具体的问题点,希望 XRay 可以帮助分析诊断问题。
分析过程
首先直接在生产环境部署 XRay。是的,XRay 不需要应用程序的配合,以非侵入的方式来分析应用程序,可以直接应用于生产环境。
面对内存方面的问题,XRay 已经集成了一成套的分析方案,具体的背景知识可以参考这些博文:
我们首先关注 OpenResty worker 进程在应用层面的内存使用情况。
我们可以看到 Stream LuaJIT 占用了大多数的内存,点击这个块看细节。
我们可以看到大部分内存是由 stream 子系统的 LuaJIT GC 所管理的,点击这个块继续分析。
我们可以看到有上百万个 table 对象,占用了大部分的内存。我们继续看 GC 对象引用关系火焰图。
在 Lua 的世界里,一个 Lua GC 对象如果有被 GC root 引用,那他就是“活着”的状态,否则就是属于 “死” 的状态,随着 GC 的工作,这个对象终将会被清理释放掉。
GC 对象引用关系火焰图,是把引用关系链以火焰图的形式展示出来,从下往上表示引用关系,宽度表示内存占用的大小。
具体到我们得到的火焰图,此时我们可以看到 ngx.ctx
上引用的对象占用了很多的内存,并且也很分散,我们选中火焰图中一个柱子看:
此时可以看到是 ngx.ctx.game_conf.tcp
上引用了 66 个 table,占用了 1MB+ 的内存,
选其他的柱子看了也都是类似的引用。
有了这个层面的关键信息,云盾的工程团队也很快就完成了优化改进。
从开始使用 XRay,到分析定位问题,优化改进,最后到上线验证确认有效,前后一共只有半天的时间。如果没有 XRay 这种精准定位问题的能力,这是无法想象的。
我们再用 XRay 来看下优化后的真实情况,总体内存占用降低了 60%+。
此时我们看到 Stream LuaJIT 占用也不高了,比优化前下降了 80%+,优化工作已经顺利完成。
worker 进程内存不释放的疑问
不过此时还有一个疑问,为什么之前流量切走之后, 内存占用也并没有很明显降低呢。 我们可以看下流量切走之后的分析,如下图
我们可以看到 LuaJIT 内存分配器管理的内存中,大部分都是在空闲的内存池中,并没有释放给操作系统。 这是因为 LuaJIT 的内存分配器有空闲内存池机制,只有当出现连续的整段空闲内存,才会将内存释放给操作系统。
我们还可以通过走势图,完整的看到内存使用变化的过程,比如下图:
从内存走势图中可见,流量切走过程中, 正在使用的内存逐步减少,空闲的内存逐步降低, 在流量切回来的时候,空闲的内存又开始被使用起来了。拨云见日,谜团解开。
-
OpenResty Inc. 是开源 OpenResty 项目创建者章亦春创建的商业公司。 ↩︎