2013-12-18 30 views
11

这可能更适合服务器故障,但我想我会在这里先问一下。在内存不足错误后,PHP自动加载错误

我们有一个前置于我们服务器上每个PHP文件的文件,这个文件使用包含我们用于自动加载,环境检测等的Bootstrap类的自动预先安排。这一切都工作正常。

然而,当存在一个“内存不足”错误直接前面的(即,小于一个第二或甚至在相同的时间)到相同的服务器上的另一个文件的请求时,三种情况之一发生:

  1. 我们检查if(class_exists('Bootstrap'),这是我们用来包裹类定义当我们第一次得到这个错误代码,返回true,这意味着阶级已经尽管这是自动前置文件中声明。

  2. 我们从我们的自动预置文件中得到“无法重新声明类Bootstrap”错误,这意味着class_exists('Bootstrap')返回false,但它以某种方式仍然被声明。

  3. 该文件根本没有被预置,导致依赖它的文件导致一次致命错误。

我们当然可以尝试修复内存不足的问题,因为这些问题似乎会导致其他错误,但由于各种原因,它们在我们的设置中不可修复或很难修复。但是,除此之外 - 在我看来,这是PHP中的一个错误,导致某些内存泄漏导致了auto-prepend指令的问题。

由于这种情况很少发生(这可能是我们的高流量服务器每周一次),所以这比任何事情都更加好奇。但我想知道 - 为什么会发生这种情况,我们该怎么做才能解决这个问题?

我们使用PHP 5.4.19运行FreeBSD 9.2。

编辑:我们一直试图在过去几个月来解决这个发现有几件事情:

  • 这似乎只是我们的安全服务器上发生。内存不足问题主要集中在我们安全的服务器上(他们通常来自我们自己的员工试图下载太多数据),所以这可能只是巧合,但值得指出

  • get_declared_classes当我们遇到这个问题时,包含在触发错误的页面上没有使用的类。例如,$_SERVER的输出表示此人在xyz.com上,但其中一个声明的类仅用于abc.com,这是内存不足问题通常来自的地方。

  • 所有这些让我相信PHP在得到内存不足错误之后没有做正确的周期结束垃圾回收,这会导致Bootstrap类在下一页的内存中完全或部分丢失如果在错误发生后足够快,请求。我对PHP垃圾收集实际上不太熟悉,但我认为这很可能是问题所在。

+1

可能。听起来像是一个坚硬的边缘案件追捕。我会使用[dtrace](http://www.php.net/manual/en/features.dtrace.dtrace.php)来记录(a)你的前置编译,(b)GC在做什么,以及(c)错误条件。对于GC位,您可能需要编写自己的[静态探针](http://blog.experimentalworks.net/2008/12/dtracing-php/)。另外,如果您正在运行APC,则会为这些诊断程序禁用它。 – bishop

+0

谢谢。现在出现这样一个难题:让我们自己相信这是一个足够大的问题,需要深入解释器和gc才能解决。 :-D – jraede

+0

您在那些服务器上使用任何类型的操作码缓存吗?你使用PHP作为模块还是(快)CGI?你的_server_内存不足,还是只是达到极限的php脚本? – Wrikken

回答

0

即使class_exists返回false,它永远不会是如果一个同名的接口存在返回true。但是,你不能声明一个接口和同名的类。

尝试运行class_exists('Bootstrap') && interface_exists('Bootstrap')以确保您不会重新声明。

+0

如果那是每次都会发生的情况。我描述的问题间歇发生,即使在同一页面上。我已经离开那家公司,但不管怎样,我们都没有使用接口。但是,感谢这个想法 – jraede