php-fpm循环调用mmap进入忙等导致服务不可用问题咨询
问题根因分析
你观测到的mmap(NULL, 2097152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)是PHP向操作系统申请2MB匿名私有内存的系统调用,进程持续循环执行该调用、同时CPU占满100%,最终触发php-fpm超时返回Service Unavailable,核心是进程进入了无限制申请内存的无限循环,常见诱因分为三类:
- 业务代码存在无终止条件的死循环,且循环内持续生成大变量、往数组追加数据或者创建无复用的大对象,没有手动释放无用内存。PHP内存管理器无法回收仍被引用的内存,就会持续向操作系统申请新的内存块,触发高频mmap调用。这种是最常见的场景,典型如忘记写自增逻辑的
while循环、遍历数据时判断条件写反导致永远不会退出循环。 - PHP内核或第三方扩展存在内存管理bug。比如特定版本的内置函数、数据库/图片处理/网络请求类扩展存在逻辑漏洞,触发后进入无限申请内存的逻辑,这种场景通常只有在特定PHP版本、特定扩展版本的组合下才会复现。
- 递归调用没有设置终止条件,递归深度持续增加的过程中,需要不断申请内存存储递归上下文、临时变量,也会触发持续的mmap调用,最终要么触发PHP内存上限报错、要么触发php-fpm进程超时返回Service Unavailable。
如果要进一步定位具体触发点,可以在脚本可疑执行节点打印memory_get_usage()的返回值,确认内存是否随执行时间线性增长;代码层面的问题可以通过二分注释法缩小范围,非代码问题可以尝试切换PHP版本、禁用非必要扩展复现验证。
内容的提问来源于stack exchange,提问作者chx
相关产品推荐
相关产品推荐

