Apache 2.4下php_network_getaddresses报错:无DNS请求发出求助
碰到这种批量服务器出现的php_network_getaddresses: getaddrinfo failed错误,且只有重启httpd24-httpd才能解决、reload无效的情况,结合你用的是mod_php嵌入Apache进程的架构,咱们可以从以下几个方向逐步排查:
1. 确认Apache进程实际读取的DNS配置
因为mod_php运行在Apache的子进程中,进程启动时会加载系统的DNS配置文件(/etc/resolv.conf),如果后续配置变更或者进程读取到的配置异常,reload操作不会让已有子进程重新加载配置(只有重启才会让所有新进程读取最新配置)。
你可以执行以下命令,查看Apache进程实际看到的resolv.conf内容:
# 取任意一个httpd24-httpd进程ID,查看其视角下的resolv.conf cat /proc/$(pidof httpd24-httpd | awk '{print $1}')/root/etc/resolv.conf
将这个结果和系统层面的/etc/resolv.conf对比,确认是否一致。如果不一致,可能是Apache进程被chroot,或者配置文件在进程启动后被修改但未同步到进程视角。
2. 排查进程内DNS解析状态异常
你提到tcpdump监控53端口时没有看到任何DNS请求,这说明PHP代码触发解析时,Apache子进程根本没发起DNS查询——大概率是进程内的DNS resolver处于异常状态,比如libc resolver的缓存出现了错误条目,或者resolver内部状态卡死。
可以做以下验证:
- 在问题服务器上创建一个简单的PHP测试脚本(比如
dns_test.php),内容如下:
<?php $host = "你要解析的域名"; var_dump(gethostbyname($host)); var_dump(dns_get_record($host, DNS_A)); ?>
通过浏览器访问这个脚本,同时用strace跟踪一个Apache子进程的系统调用,看看是否有getaddrinfo或者sendto(发送DNS请求)的调用:
# 找到一个Apache子进程ID strace -p <子进程PID> -e trace=network,getaddrinfo
如果strace里没有看到getaddrinfo的调用,说明PHP代码的解析请求被进程内的缓存拦截,但缓存的是错误结果;如果有getaddrinfo调用但没有发送UDP包,那可能是libc resolver的内部状态异常。
3. 验证opcache的影响
你提到reload无效而重启有效,结合opcache的特性:opcache是进程内的缓存,reload Apache时,父进程会启动新的子进程,但旧的子进程会继续处理现有请求直到退出——如果你的请求一直落在旧的子进程上,就会持续出现问题。另外,如果opcache缓存了包含DNS解析结果的PHP代码(比如硬编码的解析结果,或者缓存了动态解析的变量),也可能导致问题。
可以临时关闭opcache测试:修改php.ini中的opcache.enable=0,然后重启Apache,观察问题是否再次出现。如果关闭后问题消失,那需要检查opcache的配置(比如opcache.revalidate_freq),或者是否有代码将DNS解析结果缓存到了opcache中。
4. 检查系统库(glibc)的异常
getaddrinfo是glibc提供的函数,如果近期服务器更新过glibc版本,可能存在导致resolver状态异常的bug。你可以查看glibc的版本和更新记录:
# 查看当前glibc版本 ldd --version # 查看glibc的更新历史 yum history info glibc
如果发现近期有glibc更新,且更新时间和问题爆发时间吻合,可以尝试回退到之前的版本测试,或者查看RHEL的bugzilla是否有相关问题报告。
临时缓解与长期解决方案
- 临时缓解:配置Apache的
MaxRequestsPerChild参数,设置一个合理的值(比如10000),让子进程处理一定数量的请求后自动重启,避免进程长期运行导致的resolver状态异常。修改httpd.conf后需要重启Apache生效:
MaxRequestsPerChild 10000
- 长期解决:考虑将mod_php切换为php-fpm架构。php-fpm的进程独立于Apache,DNS解析问题可以通过重启php-fpm快速解决,无需重启Apache;同时可以更灵活地控制PHP进程的生命周期,降低进程异常影响范围。
内容的提问来源于stack exchange,提问作者Elijah Lynn




