这可能更适合服务器故障,但我想我先问这里。
我们的服务器上的每个PHP文件都有一个文件,它使用自动前置,其中包含一个名为Bootstrap
的类,我们用它来进行自动加载,环境检测等。这一切都正常。
但是,当在同一服务器上的另一个文件的请求之前(即,小于一秒或甚至同时)存在“OUT OF MEMORY”错误时,会发生以下三种情况之一:
我们用于检查if(class_exists('Bootstrap')
的代码(我们在第一次收到此错误时用于包装类定义)返回true
,这意味着该类已经被声明,尽管这是自动 - 文件。
我们在自动预装文件中收到“无法重新声明类Bootstrap”错误,这意味着class_exists('Bootstrap')
返回false
但仍以某种方式声明了它。
当然,我们可以尝试修复内存不足问题,因为这些问题似乎导致了其他错误,但由于各种原因,它们在我们的设置中无法修复或者很难修复。但这不是重点 - 在我看来,这是PHP中的一个错误,存在某种内存泄漏导致auto-prepend指令出现问题。
这比任何事情都更好奇,因为这很少发生(可能每周一次在我们的高流量服务器上)。但我想知道 - 为什么会发生这种情况,我们可以做些什么来解决它?
我们正在使用FreeBSD 9.2
运行PHP 5.4.19
。
似乎只发生在我们的安全服务器上。内存不足问题主要出现在我们的安全服务器上(他们通常来自我们自己的员工,试图下载太多数据),所以这可能只是巧合,但值得指出
遇到此问题时,get_declared_classes
的转储包含未在触发错误的页面上使用的类。例如,$_SERVER
的输出表示此人在xyz.com上,但其中一个声明的类仅用于abc.com,这是内存不足问题通常源自的地方。
所有这些让我相信PHP在获得内存不足错误后没有进行正确的循环结束垃圾收集,导致Bootstrap
类完全或部分地处于如果错误发生后很快就会在下一页请求内存。我对PHP垃圾收集的熟悉程度不足以实际采取行动,但我认为这很可能是问题所在。
答案 0 :(得分:0)
即使class_exists
返回false,如果存在同名的接口,它也永远不会返回true。但是,您不能声明具有相同名称的接口和类。
尝试运行class_exists('Bootstrap') && interface_exists('Bootstrap')
以确保不重新声明。
答案 1 :(得分:0)
您看过__autoload函数吗?
我相信您可以通过在代码中创建类似的功能来解决此问题:
function __autoload($className)
{
if (\file_exists($className . '.php'))
include_once($className . '.php');
else
eval('class ' . $className . ' { function __call($method, $args) { return false; } }');
}
如果您有一个名为Bootstrap.php的文件,并且其中声明了Bootstrap类,则PHP将自动加载文件,否则声明一个可以处理其中任何函数调用的ghost类,从而避免出现任何错误消息。请注意,对于幻影功能,我使用了__call魔术方法。
答案 2 :(得分:0)
如果不解决内存不足问题,可能无法“解决”问题。在不知道您使用的框架的情况下,我将仅列出需要考虑的领域。
您说“他们通常来自我们自己的员工,试图下载过多的数据”。我将从这里开始,因为这可能是最大/最大的优化机会,所以我想到了一些想法。
如果正在下载的数据是文件,也许您可以使用流将读取的数据块化为恒定大小,这样在大下载量时不会占用内存。
您可以下载队列,限制吗?
如果数据来自数据库,则除了优化查询之外,您还可以对查询进行速率限制,减小结果集大小,并理想地将此类工作负载转移到具有镜像数据的专用环境中。
确保您的代码以负责任的方式释放文件指针和数据库连接,将其留给PHP拆除,这可能会在高流量情况下导致垃圾回收延迟和某种级联效果。
关于记忆力限制的其他低落果实
您正在运行php 5.4.19,如果您的软件允许,请考虑更新到更新版本“ PHP 5.4自2015年以来未进行修补”,而PHP 7则带来了很多性能改进。
如果您有客户端应用程序在监视它的xhr和整个网络活动,请查找过多的轮询和挂起连接。
对于自动加载器,基于您的注释“我们遇到此问题时,get_declared_classes的转储包含触发错误的页面上未使用的类”,您可能需要检查实现,以使确保它没有加载某种捆绑的类缓存,如果您使用的是作曲家,则dump-autoload可能会有所帮助。
会话,我已经看到一些应用程序基于cookie和会话加载文件,如果您有这样的设置,我会审核该逻辑并确保没有粘性会话加载不需要的资源。
从您的问题很明显,您正在运行多租户服务器。没有适当的统计数据,很难具体说明,但我认为这显然不是PHP问题,因为根据您的描述,它似乎有些孤立。
我建议安装一个PHP探查器,即使是很短的时间,新的文物也不错。您将能够准确了解正在发生的事情,并拥有解决正确问题的数据。我认为他们有免费试用版,应该可以使您指明正确的方向……也有其他人,但是他们的名字此刻不在我眼前。