我们能够追踪导致运行 Magento 的 NGINX 服务器崩溃的问题,直到以下几点:
背景信息:Magento Backend 具有 CMS 功能和所见即所得编辑器。此编辑器通过 magento 中的控制器 (cms/directive) 加载一些图片。
当我们将 NGINX error_log 级别设置为 info 时,我们得到以下几行(插入换行符以提高可读性):
2012/10/22 18:05:40 [info] 14105#0: *1 client closed prematurely connection,
so upstream connection is closed too while sending request to upstream, client:
XXXXXXXXX, server: test.local, request: "GET
index.php/admin/cms_wysiwyg/directive/___directive/BASEENCODEDIMAGEURL,,/
HTTP/1.1",
upstream: "fastcgi://127.0.0.1:9024", host: "test.local"
在调试器中检查代码时,以下调用永远不会返回(在“Varien_Image_Adapter_Abstract::getMimeType()”中)
# $this->_fileName is http://test.local/skin/adminhtml/base/default/images/demo-image-not-existing.gif`
# $_SERVER['REQUEST_URI'] = http://test.local/admin/cms_wysiwyg/directive/___directive/BASEENCODEDIMAGEURL
list($this->_imageSrcWidth, $this->_imageSrcHeight, $this->_fileType, ) = getimagesize($this->_fileName);
文件名请求是
- 请求脚本的同一服务器的 URL
- 指向不存在的静态 .gif 的链接。
示例网址:
http://test.local/skin/adminhtml/base/default/images/demo-image-not-existing.gif
执行上述代码后,对 NGNIX 服务器的任何后续请求都不再响应。等待大约 10 分钟后,NGINX 服务器再次开始响应请求。
我尝试使用一个仅使用getimagesize()
给定 URL 调用的简单测试脚本来重现该错误 - 但这并没有崩溃。它只是导致一个异常,提示无法加载 URL(这没关系,因为 URL 是错误的)
答案1
当前理论:
NGINX / PHP FCGI 可以处理的进程数量有限。CMS WYSIWYG 编辑器针对cms_wysiwyg/directive
NGINX 尝试完成的操作触发大约 5 个并行请求。假设 NGINX 只能处理 5 个并行请求:现在 NGINX 在其中一个正在运行的请求中向自己发出一个额外请求,该请求当然无法满足,因为插槽已满。插槽也无法释放,因为满足一个请求取决于发出一个额外请求。
可能的解决方案:
- 增加槽数
- 当插槽已满时,让请求尽快失败
答案2
我刚刚遇到了几乎相同的问题。查看包含已上传图像的 CMS 块后,整个 php/php-fpm 设置变得无响应。
问题原来是调用 getimagesize(在我的情况下是 lib/Varien/Image/Adapter/Gd2.php 中的第 72 行左右)。尽管有问题的图像文件位于网站本身,但 getimagesize 的参数是 HTTP URL。由于奇怪的防火墙配置,服务器无法通过 HTTP 连接自身,因此请求挂起,出于未知原因,php-fpm 完全停止处理请求。
最后 nginx 失去了耐心,记录了超时错误。
允许服务器向自身发出 HTTP 请求后,超时错误就消失了。
我仍然不明白为什么 Magento 会通过 HTTP 访问本地文件,但这可能是在所见即所得编辑器中支持外部图像的最简单方法。
(Magento 1.8.1.0)