【PHP】大量 HTTP 请求调第三方接口,接口堵塞引起的 FD 耗尽(too many file open)问题
“FD耗尽”中的“FD”指的是“文件描述符”(File Descriptor)。在Unix和类Unix系统(如Linux)中,文件描述符是一个非负整数,用于标识一个进程打开的文件或其他输入/输出资源,比如网络套接字(sockets)。
当发起大量的HTTP请求,尤其是如果这些请求是同步阻塞的,并且第三方接口响应时间较长,那么每个未完成的请求都会占用一个文件描述符。如果系统中可用的文件描述符数量有限,而消耗的速度超过了释放的速度,最终就会达到系统的上限,导致“FD耗尽”的情况。通常表现为“Too many open files”之类的错误信息。
为了避免这种情况,可以采取以下措施:
- 使用异步或非阻塞的IO模型,这样多个请求可以共享较少的文件描述符。
- 增加系统的最大文件描述符限制(通常通过调整
/proc/sys/fs/file-max
或修改ulimit -n
设置)。 - 实现请求的限流或排队机制,避免短时间内发送过多请求。
- 优化第三方接口的响应时间,或者使用缓存策略减少直接调用的频率。
- 正确地关闭不再需要的连接,确保文件描述符得到及时释放。
对于第1种解决方案,传统上PHP并不支持异步编程,尤其是在脚本模式下运行时,它默认是同步阻塞的。不过,随着技术的发展,PHP也有了一些异步解决方案,比如使用Swoole或ReactPHP这样的扩展库,它们能够提供异步I/O和协程的支持,允许你在PHP中编写非阻塞代码。
在我们项目中,采用了对外部接口限流的方法来解决的。并调整了系统和PHP的最大文件数量。同时也降低了curl的超时时间和请求超时时间。