https://blog.openresty.com.cn/cn/ngx-cycle-pool-frag/?src=org_news
章亦春发布于 Feb 14, 2023更新于 Mar 2, 2023

预计阅读 6 分钟
阅读次数
 

我们最近使用 OpenResty XRay 帮助一个销售 CDN 和流量网关服务的企业客户优化了他们的 OpenResty/Nginx 服务器的内存使用。这个客户在他们的 OpenResty/Nginx 配置文件中定义了许多虚拟服务器和 URI location。OpenResty XRay 在客户的生产环境中自动进行了大部分分析,基于分析结果给出的方案让 nginx 进程的内存占用减少了大约 30%。

和我们的 OpenResty Edge 的 nginx worker 进程相比显示, 进一步的优化将会继续减少约 90%。

OpenResty XRay 是一个动态追踪产品,它可以自动分析正在运行中的应用程序,以排除性能问题、行为问题和安全漏洞,并提供可行的建议。在底层实现上,OpenResty XRay 由我们的 Y 语言驱动,可以在不同环境下支持多种不同的运行时,如 Stap+, eBPF+, GDB 和 ODB。

挑战

这个 CDN 供应商使用一个超大的“nginx.conf”配置文件来为他们的 OpenResty 服务器中的近万个虚拟主机服务。每个 nginx 主进程在启动后占用了好几个 G 的内存,在一次或多次 HUP reload 后,内存几乎翻倍。从下面 OpenResty XRay 生成的图中可以看出,最大内存占用约为 4.60GB。

我们可以从 OpenResty XRay 的应用层面内存使用明细表中看到,Glibc 分配器占用了大部分常驻内存,有 4.55GB。

而 OpenResty XRay 发现 Nginx cycle pool 占用了大量的内存:

当 Nginx 加载配置文件时,我们都知道它为这个 cycle pool 内的配置数据分配了数据结构。虽然庞大到有 1.62GB,但远远小于上面提到的 4.60GB。

RAM 依然是昂贵和稀缺的硬件资源,特别是在 AWS 和 GCP 这样的公有云上。客户希望通过降级到内存较小的机器来节约成本。

分析

OpenResty XRay 对客户的在线进程进行了深入分析。它不需要客户的应用程序进行任何协作。

  • 没有额外的插件、模块或库。
  • 没有代码注入或补丁。
  • 没有特殊的编译或启动选项。
  • 甚至不需要重新启动应用程序进程。

分析完全是以“事后”的方式进行的。多亏了 Openresty XRay 采用的动态追踪技术。

太多的空闲区块

OpenResty XRay 用 Glibc 内存分配器的分析器自动对在线 nginx 进程进行采样。分析器生成了以下柱状图,显示了分配器管理的空闲块的大小是如何分布的。

Glibc 分配器通常不会立即释放空闲块给操作系统(OS)。它可能会保留一些空闲块,以加快后续的分配速度。但有意保留的通常很小,不可能到上 G 字节。这里我们看到空闲块的大小累计已经达到 2.3GB。因此,更常见的原因是内存碎片。

查看普通堆中的内存碎片问题

大多数小的内存分配通过 brk Linux 系统调用,发生在“普通堆”中。这个堆就像一个线性的 “堆“,只能通过移动其”顶部"指针来增加或减少。在堆中间的所有空闲块不能被释放给操作系统。直到它们上面的所有块也变成空闲,它们才会被释放。

OpenResty XRay 的内存分析器可以帮助我们查看这种堆的状态。请看下面的堆图,它是在 nginx 主进程响应 HUP 信号加载新配置后的采样图。

我们可以看到,堆是向上增长的,也就是说,向高位内存地址增长。注意 brk top 指针,这是唯一可以移动的东西。绿色框属于 Nginx 的新 “cycle pool“,而粉色框属于旧 ”cycle pool”。一个有趣的现象是,Nginx 会保留旧的 cycle pool 或旧的配置数据,直到新的 cycle pool 被成功加载。这种行为是由于 Nginx 的保护机制,当新的配置加载失败时,会优雅地退回到旧的配置。不幸的是,正如我们在上面看到的,旧的配置数据的盒子(绿色)在新的数据(粉色)下面,因此只有当新的配置数据也被释放后,它们才能释放到操作系统。

事实上,在 Nginx 释放了旧的配置数据和旧的 cycle pool 后,它们原来的位置变成了空闲块,被卡在新的 cycle pool 的块下面。

这是一个教科书式的内存碎片化的例子。普通堆只能在顶部释放内存;因此,它比其他内存分配机制,如 mmap 系统调用,更容易受到内存碎片的影响。但是,mmap 会在这里拯救我们吗?不一定。

mmap 的世界

Glibc 分配器也可以通过 mmap 系统调用来分配内存。这些系统调用分配离散的内存块或内存段,这些内存块或内存段可能位于进程地址空间的几乎任何地址,并跨越任何数量的内存页。

这听起来是一个缓解上述内存碎片问题的好方法。但是当我们有意阻断普通堆的增长方式时,根据 OpenResty XRay 的分析器所产生的图表,类似程度的内存碎片仍然发生。

当应用程序(这里是 Nginx)请求分配较小内存块的时候,Glibc 倾向于分配相对较大的内存段,这里是 1MB。因此,内存碎片仍然会发生在这些 1MB 的 mmap 段内。如果一个小内存块仍在使用,那么整个内存段就不会被释放给操作系统。

在上图中,我们可以看到旧的 cycle pool 块(粉红色)和新的 cycle pool 块(绿色)仍然在许多 mmap 段中交错。

解决方案

我们为客户提出了几个解决方案。

简单方式

最简单的方式是直接解决内存碎片的问题。根据上面我们使用 OpenResty XRay 做的分析,我们应该做以下一个或多个变动。

  1. 避免在“普通堆”中分配 cycle pool 内存(即取消这种分配的 brk 系统调用)。
  2. 要求 Glibc 使用适当的 mmap 段内存大小(不要太大!)来满足 cycle pool 的内存分配请求。
  3. 将不同 cycle pool 的内存块干净地分离到不同的 mmap 段中。

我们为 OpenResty XRay 的付费客户提供详细的优化说明。因此根本就不需要编码。

更好的方式

是的,还有一个更好的方式。开源的 OpenResty 软件提供了 Lua APIs 和 Nginx 配置指令,以动态加载(和卸载)Lua 层面的新的配置数据,而不需要通过 Nginx 配置文件机制。这使得使用一个小的恒定大小的内存来处理更多的虚拟 server 和 location 的配置数据成为可能。同时,Nginx 服务器的启动和重新加载时间也大大缩短(从很多秒到几乎为零)。事实上,有了动态配置加载,HUP reload 操作本身变得非常罕见。这种方式的一个缺点是,这需要在我们用户侧进行一些额外的 Lua 编码。

我们的 OpenResty Edge 软件产品以 OpenResty 作者所设想的最佳方式实现了这种动态配置加载和卸载。它不需要用户进行任何编码。所以这也是一个容易的选项。

结果

这位客户决定先尝试简单的方式,结果在几次 HUP reload 后,总的内存占用减少了 30%。

仍然有一些剩余的片段值得进一步关注。但我们的客户已经很满意了。此外,上面提到的更好的方式可以节省超过 90% 的总内存占用(就像在我们的 OpenResty Edge 产品中一样):

关于作者

章亦春是开源 OpenResty 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。

章亦春(Github ID: agentzh),生于中国江苏,现定居美国湾区。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、雅虎、阿里巴巴, 是 “边缘计算“、”动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者。他基于其 OpenResty 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的两个产品 OpenResty XRay(利用动态追踪技术的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最适合微服务和分布式流量的全能型网关软件),广受全球众多上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJITGDBSystemTapLLVM、Perl 等,并编写过 60 多个开源软件库。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。

我们也在 B 站上也有 OpenResty 官方的视频分享空间,欢迎订阅。

同时欢迎扫码关注我们的微信公众号:

[转帖]优化超大 Nginx 配置导致的内存碎片的更多相关文章

  1. Nginx使用教程(三):Nginx配置性能优化之I/O和TCP配置

    配置Nginx I/O <br\> Sendfile 当应用程序传输文件时,内核首先缓冲数据,然后将数据发送到应用程序缓冲区. 应用程序反过来将数据发送到目的地. Sendfile方法是一 ...

  2. [转帖]nginx配置ssl加密(单/双向认证、部分https)

    nginx配置ssl加密(单/双向认证.部分https) https://segmentfault.com/a/1190000002866627   nginx下配置ssl本来是很简单的,无论是去认证 ...

  3. Nginx服务器性能优化与安全配置实践指南

    转载自:https://www.bilibili.com/read/cv16151784?spm_id_from=333.999.0.0 1.引言 1.1 目的 为了更好的指导部署与测试艺术升系统ng ...

  4. Nginx配置性能优化

    大多数的Nginx安装指南告诉你如下基础知识--通过apt-get安装,修改这里或那里的几行配置,好了,你已经有了一个Web服务器了.而且,在大多数情况下,一个常规安装的nginx对你的网站来说已经能 ...

  5. nginx 配置优化的几个参数

    nginx 配置优化的几个参数 2011-04-22 本文地址: http://blog.phpbean.com/a.cn/7/ --水平有限欢迎指正-- -- 最近在服务器上搞了一些nginx 研究 ...

  6. Nginx配置性能优化(转)

    大多数的Nginx安装指南告诉你如下基础知识——通过apt-get安装,修改这里或那里的几行配置,好了,你已经有了一个Web服务器了.而且,在大多数情况下,一个常规安装的nginx对你的网站来说已经能 ...

  7. Nginx配置性能优化与压力测试webbench【转】

    这一篇我们来说Nginx配置性能优化与压力测试webbench. 基本的 (优化过的)配置 我们将修改的唯一文件是nginx.conf,其中包含Nginx不同模块的所有设置.你应该能够在服务器的/et ...

  8. Nginx配置不当可能导致的安全问题

    Nginx配置不当可能导致的安全问题 Auther: Spark1e目前很多网站使用了nginx或者tenginx(淘宝基于Nginx研发的web服务器)来做反向代理和静态服务器,ningx的配置文件 ...

  9. 关于Nginx配置性能优化

    基本的 (优化过的)配置 将修改的唯一文件是nginx.conf,其中包含Nginx不同模块的所有设置.在服务器的/etc/nginx目录中找到nginx.conf. 首先,我们将谈论一些全局设置,然 ...

  10. Nginx配置优化参考

    Nginx配置优化参考                                                                                          ...

随机推荐

  1. OSG嵌入QT的简明总结2

    正文 我之前在这篇博文<OSG嵌入QT的简明总结>中论述了OSG在QT中显示的可视化问题.其中提到官方提供的osgQt项目(地址:https://github.com/opensceneg ...

  2. TreeMap - 红黑树

    TreeMap是Map家族中的一员,也是用来存放key-value键值对的.平时在工作中使用的可能并不多,它最大的特点是遍历时是有顺序的,根据key的排序规则来 TreeMap是一个双列集合,是Map ...

  3. SpringBoot Admin OFFLINE

    java.util.concurrent.TimeoutException message Did not observe any item or terminal signal within 100 ...

  4. 【短道速滑二】古老的基于亮度平均值的自动Gamma校正算法。

    在github上搜索代码Auto Gamma Correction,找到一个比较古老的代码,详见:https://github.com/PedramBabakhani/Automatic-Gamma- ...

  5. WebSoket 的广泛应用

    目前大多数网站都在使用的传统 HTTP 协议,即由 Web 服务器通过 HTTP 接收并响应来自客户端的消息,整个发起请求与响应的过程类似我们点外卖,由以下 2 部分构成: 下订单(发起请求):用户( ...

  6. 【HZERO】权限管理

    Hzero数据权限介绍 https://open.hand-china.com/community/detail/625872021372407808#3.4 开发建议 Permission注解属性介 ...

  7. OS | 进程和线程基础知识全家桶图文详解✨

    前言 先来看看一则小故事 我们写好的一行行代码,为了让其工作起来,我们还得把它送进城(进程)里,那既然进了城里,那肯定不能胡作非为了. 城里人有城里人的规矩,城中有个专门管辖你们的城管(操作系统),人 ...

  8. KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)(AB水题,C思维,D搜索,E DP)

    补题链接:Here A - Century 整除 \(200\) 并且判断能否整除完全 B - 200th ABC-200 按题意即可 C - Ringo's Favorite Numbers 2 求 ...

  9. 关于 Windows10升级版本后,内存占用率居高不下的解决办法

    一个月前,打开系统更新,win 10 推送了 最新版本. 然后手贱点了更新. 的确一开始没觉得的有什么明显变化,但最近总觉得机子卡的卡的严重,查看了下内存,占用率居高不下. 经常才打开一两个软件内存就 ...

  10. InnoDB 事务加锁分析

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/S7MhlsZveBHRSQhq5aTIJA作者:何志创 一般大家对数据库事务的了解可能停留在事 ...