卡在“Resolving dependencies”是PHP-FPM worker复用导致DNS缓存长期持有,非Composer配置问题;应通过php -r验证DNS一致性、禁用fallback、绑定hosts或重启worker解决。

PHP-FPM里跑composer install为什么卡在Resolving dependencies
因为 PHP-FPM 的 fastcgi 进程复用导致 DNS 缓存被长期持有,Resolving dependencies 卡住几十秒不是 Composer 配置问题,而是底层 getaddrinfo() 调用被旧 DNS 结果阻塞。CLI 模式下每次执行都是新进程,DNS 会重新查;FPM 下一个 worker 可能跑几天,缓存不刷新就一直用错的 IP。
怎么确认是 FPM DNS 缓存而非镜像配置失效
别急着改 composer.json 或重配镜像源。先做三件事:
- 在 FPM 环境里直接执行:
php -r "var_dump(gethostbyname('mirrors.aliyun.com'));",对比 CLI 下输出是否一致 - 查 FPM worker 日志末尾是否有
php_network_getaddresses: getaddrinfo failed类错误 - 运行
composer diagnose,若提示https connectivity to packagist.org失败,但你明明配了镜像——说明它 fallback 到了官方源,而 fallback 的触发点正是 DNS 解析失败
绕过 FPM DNS 缓存的实操方案
FPM 本身不提供 DNS 刷新接口,只能从调用层或系统层切断缓存链:
- 强制禁用 fallback:加环境变量
COMPOSER_DISABLE_FALLBACK=1,避免 DNS 失败后自动切回 packagist.org - 绑定 hosts:在
/etc/hosts(Linux/macOS)或C:\Windows\System32\drivers\etc\hosts(Windows)里写死镜像 IP,例如223.5.5.5 mirrors.aliyun.com - 换 DNS 解析器:在 FPM 的
www.conf里加env[HOSTALIASES] = /dev/null,并确保系统/etc/resolv.conf用的是 8.8.8.8 或 223.5.5.5 - 关键补丁:PHP 8.1+ 支持
dns_get_record()的DNS_NOCACHE标志,但 Composer 不用这个函数;所以必须让整个 PHP 进程不依赖系统缓存——最稳方式是重启 FPM worker(kill -USR2 $(cat /var/run/php/php8.1-fpm.pid))
为什么改了 http.timeout 还没用
http.timeout 控制的是 HTTP 请求生命周期,而 Resolving dependencies 卡住时,Composer 还没发任何请求,连 gethostbyname() 都卡在内核 DNS 查询阶段。此时调整 http.timeout、process-timeout 或 PHP 的 default_socket_timeout 全无效。真正要动的是系统 DNS 行为和 FPM 进程生命周期。
立即学习“PHP免费学习笔记(深入)”;
最容易被忽略的一点:FPM 的 pm.max_requests 设得太大(比如 10000),会导致 worker 永远不重启,DNS 缓存就永远不更新。设成 500~1000 更安全。



















