PHP操作码缓存锁定Apache。可能与Symfony2-Doctrine2有关。

13

我开发了大约10个不同的网站,托管在下面提到的单个服务器上。

故事:

一切都很顺利,直到我决定将PHP Opcode缓存集成到系统中。我首先尝试了APC,但使用Xcache时出现了相同的问题,因此我不认为与缓存程序本身有关。

该系统在一段时间内保持稳定,时间从一天到一周不等,并且在不同的时间崩溃,但主要是在晚上23点至05点左右。如果我重新启动httpd服务,则系统在同一时期内(1天至1周)保持稳定,然后再次崩溃等等...

Bug报告:

这是我在最后一次崩溃期间的httpd全局日志报告:

[Thu Feb 18 20:00:11.270997 2016] [core:notice] [pid 24956:tid 139940499228480] AH00052: child pid 4522 exit signal Aborted (6)
httpd: hostip.c:693: Curl_resolv_unlock: Assertion `dns && (dns->inuse>0)' failed.
[Thu Feb 18 20:08:38.793218 2016] [core:notice] [pid 24956:tid 139940499228480] AH00052: child pid 6246 exit signal Aborted (6)
httpd: hostip.c:693: Curl_resolv_unlock: Assertion `dns && (dns->inuse>0)' failed.
[Thu Feb 18 22:12:33.576308 2016] [core:notice] [pid 24956:tid 139940499228480] AH00052: child pid 8362 exit signal Aborted (6)
httpd: hostip.c:693: Curl_resolv_unlock: Assertion `dns && (dns->inuse>0)' failed.
[Thu Feb 18 22:40:07.297428 2016] [core:notice] [pid 24956:tid 139940499228480] AH00052: child pid 10224 exit signal Aborted (6)
[Thu Feb 18 23:00:40.526867 2016] [core:warn] [pid 24956:tid 139940499228480] AH00045: child process 10846 still did not exit, sending a SIGTERM
...

请注意,服务器在22:41:xx左右变得阻塞。我在23:00:xx重新启动了服务器,这与此处发布的最后一行有关。

可能与curl有关,我经常使用它,特别是PHP curl_multi,以便通过同时启动它们来加速我的API调用。但是即使没有安装(或禁用)任何PHP opcode缓存,也会发生同样的错误,但不会使服务器崩溃。

服务器状态:

当“崩溃”发生时,系统仍然可以提供任何txt、image等文件,但无法提供任何PHP文件。服务器被锁定,当查看“Apache服务器状态”时,可能有数百个请求处于“W”状态,并且随着每个传入请求增加而增加。

缓存实现:

如上所述,我尝试使用APC和xCache,但两者都出现了同样的问题。我的PHP是一个编译版本(我没有编译自己)。所有网站上方都有一个Varnish缓存,只缓存一些耗时的页面。我使用Symfony2和Doctrine2,在Doctrine2和xcache/apc之间通过Symfony2配置建立了链接:

doctrine:
    orm:
        auto_generate_proxy_classes: prod
        auto_mapping: true
        metadata_cache_driver: xcache
        result_cache_driver: xcache
        query_cache_driver: xcache

似乎让Doctrine2可以缓存实体对象并产生更好的性能(仅启用缓存对Doctrine2来说不足够)

规格说明:

- Debian 7.8
- Apache 2.4.12
- Mysql 
- PHP 5.4.38 (compiled version)
- Varnish
- Symfony 2.4.x

我已经寻找解决方案几个月了,在没有任何opcode缓存的情况下运行PHP-Symfony2网站速度非常慢,如有任何提示或帮助将不胜感激。


你在 app.php 文件中使用哪个自动加载器? - COil
我使用 "ApcClassLoader" 并带有 try catch,所以当使用 xcache 时,我猜它会回退到默认的 " $loader = require_once DIR.'/../app/bootstrap.php.cache'; "。 - elwood
请查看这个链接,也许可以帮到你:http://stackoverflow.com/questions/30780761/symfony2-bootstrap-php-cache-tries-to-include-a-non-existent-file - COil
很遗憾,我的问题与APC无关,因为完全相同的问题在使用xcache时发生,而没有特定的自动加载程序。 - elwood
"prod"。我已经在我的主贴中添加了这个信息。 - elwood
显示剩余3条评论
4个回答

5

您是否有在服务器崩溃时运行的特定cron作业?

无论如何,如果您在日志中看到Curl_resolv_unlock: Assertion 'dns && (dns->inuse>0)' failed,这意味着您在PHP中激活了“调试构建”的libcurl,这是不好的。

您的评论提到PHP说Apache 2.0处理程序,因此它正在作为Apache模块运行。

当libcurl中发生调试断言时,它会导致进程(PHP)终止。基本上我认为正在发生的是,Apache的PHP进程(处理所有PHP请求)正在死亡。这就是为什么您仍然可以提供静态资源,但PHP进程继续堆积的原因。

cURL 7.26.0相当老(2012年5月)。我建议安装更新版本的libcurl,然后重新编译PHP并确保cURL不是调试构建,并查看是否有所帮助。


问题在于没有操作码缓存时服务器不会崩溃,但是日志中会出现相同的错误,所以我不明白为什么缓存会影响cUrl。我会尝试更新cUrl并像你建议的那样使用非调试版本,如果有帮助我会告诉你的。作为最后的解决方案,我认为我们将重新安装整个堆栈,使用最新的php/cUrl和apache版本。 - elwood
我不确定为什么没有启用Opcache时你为什么没有看到PHP完全崩溃(可能是因为Apache重新加载了PHP模块,所以你没有看到任何效果),但也许由于缓存涉及使用共享内存,当PHP崩溃而不释放该内存时会出现问题。 - drew010

2

我的服务器API是"Apache 2.0 Handler"

你应该一定要检查是否在PHP-FPM下发生了类似的行为。Apache SAPI意味着它没有与httpd的内存空间分离,而是使用FPM池进程。

我怀疑你遇到了一些无法轻易追踪的内存泄漏问题。更改为FPM还可以让您在一段时间后(请求数量)自动重新启动响应器,这比定时和检查进程是否正常运行要优雅和灵活得多。

老实说,我已经有一段时间没有看到过通过Apache SAPI连接的PHP了。 :)


0

我不能为您提供确切的解决方案,但我可以向您建议一个“技巧”,以解决您的问题,并提出“调试”想法。

技巧:您可以启动一个监控,每5-10分钟通过curl请求您的网站之一,如果他得到负面响应或请求超时过期(将其设置为30秒或1分钟等较大的数字),则重新启动您的服务器+您可以清除您的然后重新启动。

调试:要调试您的问题,您可以从<内存监视>开始。我猜问题的根源是在错误期间您的系统内存泄漏,这使得您的服务器崩溃,这意味着您必须使用等方法来调试和处理您的错误。


我已经实现了几天前你建议的类似技巧,但还是感谢您指出这一点:-)。对于调试部分,我已经尝试过测试那种内存泄漏,但似乎CPU超载比内存更多。无论如何,不幸的是,这对我没有任何解决办法,因为它没有帮助找到问题的根源。 - elwood

0

我有一个使用pthreads和curl的cron php脚本,现在遇到了问题。

php: hostip.c:693: Curl_resolv_unlock: Assertion `dns && (dns->inuse>0)' failed.

我不确定,在curl中你有这个选项:

CURLOPT_DNS_USE_GLOBAL_CACHE TRUE表示使用全局DNS缓存。此选项不是线程安全的,默认情况下启用。

将其更改为FALSE,即使我运行许多线程调用同一位置的许多URL,也无法出现此错误...只有在我快速连续发出大量请求时才开始显示此错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接