You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Apache 2.4下php_network_getaddresses报错:无DNS请求发出求助

排查RHEL 7.4上mod_php突发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

火山引擎 最新活动