限制 PHP 脚本的建议/技巧

Posted

技术标签:

【中文标题】限制 PHP 脚本的建议/技巧【英文标题】:Suggestions/Tricks for Throttling a PHP script 【发布时间】:2010-10-19 15:15:27 【问题描述】:

我有一个定期(每小时)运行脚本的计划任务。该脚本与数据库和文件系统进行了一些繁重的交互,并且通常需要几分钟才能运行。问题是,脚本运行时服务器的 cpu 使用率达到峰值并减慢正常操作。有没有办法限制这个过程,使其花费更长的时间但不会消耗太多资源?

我查看了 php 的不同配置选项,但似乎没有任何适合我的需要。

将 php.ini 中的 memory_limit 设置为较低的值会导致我的数据对象很容易溢出。

我看到过类似的帖子,人们建议在脚本中的某些点使用 sleep() ,但这并不能阻止脚本对服务器的刺激。

最佳解决方案是通过某种方式告诉 Lamp(在本例中为 Wamp)堆栈仅使用 10% 的最大 cpu 利用率。我根本不关心运行时间,如果这意味着每秒节省 cpu 周期,我宁愿花费更长的时间。我的替代解决方案是设置一个具有数据库复制功能的不同服务器,这样 cron 就可以在不减慢其他所有速度的情况下运行。

环境:Windows Server 2k3、Apache 2.2.11、PHP 5.2.9、mysql 5.1

感谢您对这种情况的任何见解。

编辑:我很欣赏所有答案,即使是 *nix 特定的答案。在我的情况下,改变托管环境还为时过早。希望这个问题能帮助其他人,无论操作系统如何。

【问题讨论】:

【参考方案1】:

也许您的脚本只是试图一次做太多事情。每小时跑三遍会不会少一点?

另一种解决方案可能是设置一个额外的服务器来运行这种“后端”处理。如果它没有在数据库中(仅在 Web 服务器中)施加过多的负载,这将特别有效。

另一种看待方法是它的工作是否可以朝不同的方向划分。这些类型的脚本通常有一些大的 SQL 语句,这些语句生成的结果用于生成大量的小 SQL 语句。如果后者可以放在某处,则可以在稍后的步骤中针对数据库运行它们。这种方法还可以让您使用无缓冲查询来获取预处理数据,这可以显着减少 PHP 代码的内存消耗。

【讨论】:

【参考方案2】:

UNIX (LAMP) 中,我设法通过在继续循环之前检查服务器的负载来解决问题

function get_server_load($windows = 0) 
    $os = strtolower(PHP_OS);
    if(strpos($os, "win") === false) 
        if(file_exists("/proc/loadavg")) 
         $load = file_get_contents("/proc/loadavg");
         $load = explode(' ', $load);
         return $load;
        
        elseif(function_exists("shell_exec")) 
         $load = explode(' ', `uptime`);
         return $load;
        
        else 
         return "";
        
    


for(... ... ...)
    $data = get_server_load(); 
    if($data[0] < 0.2)
     // continue
    else
        sleep(1);
    

这个功能应该也可以在 Windows 上工作,但我不能保证。在 linux 上,它会返回一个数组,其中包含最后 1 分钟、5 分钟和 15 分钟的负载

另外,考虑以较低的优先级启动脚本(如果通过 CLI)(在 Linux 中,使用“nice”)

您还可以在继续循环之前使用其他值,例如 Apache 活动进程的数量(如果您在 httpd.conf 中启用了 mod_status,您可以解析页面 127.0.0.1/server_status?auto),或者 MySQL 情况(活动连接?)

【讨论】:

【参考方案3】:

我有一堆脚本,我使用 nice 以类似的方式从 cron 运行:

0 * * * * nice -n19 php myscript.php

这对 RAM 利用率没有帮助(只有改变脚本的编写方式才能做到这一点),但它只使用原本空闲的 CPU。

编辑:没有看到这个问题涉及 Windows 环境,抱歉...把这个留给任何有同样问题的 *nix 用户..

【讨论】:

【参考方案4】:

不是一个好主意,使用服务器为客户提供服务和分析数据。

因此,如果您正在寻找最终解决方案,请对您的应用程序进行一些重新设计,并将数据分析从前端和实时数据库转移到另一个专门用于此任务的系统。

即使您可以成功地限制分析器,它也会消耗宝贵的资源,否则可以为用户提供服务。

【讨论】:

【参考方案5】:

您能否更改您的 cron 条目以使用 nice 启动您的脚本?

【讨论】:

糟糕,抱歉。我看到你正在运行 Windows。我被“lamp”和“cron”标签吓跑了! 感谢您的回答。在我的情况下,改变环境仍然是可能的,所以我仍然发现你的解决方案很有帮助。【参考方案6】:

这是一个棘手的问题。如果您通过命令行运行 PHP 脚本,您可以将进程的调度优先级设置为低(start /low php.exe myscript.php 我相信)。如果您的 PHP 脚本本身实际上正在执行大部分消耗 CPU 的处理,那么这可能会起作用。但是,您说您正在执行一些繁重的数据库和文件系统交互,此解决方案将无济于事。看起来对于 INSERT 和 UPDATE 查询有一个 MySQL 提示“LOW_PRIORITY”可以帮助你,但我没有尝试过。

【讨论】:

【参考方案7】:

如果你有它(Apache)作为服务运行,你可以改变优先级 Win 控制中心 /services 中的设置。 无论如何,您的 CPU 使用率都会飙升,但其他程序将是首选 由调度程序。 还可以尝试将数据库/服务器放在与您的不同的高清上 应用程序。

【讨论】:

【参考方案8】:

You can set processes in Windows to be a lower priority.我不确定进程是如何启动的,但是如果你将进程设置为低优先级,那么如果你将优先级设置为非常低,那么任何想要的 CPU 资源都会得到它们。

【讨论】:

【参考方案9】:

这可能是一个艰难的改变,但将数据结构重构为迭代器可能是值得的。此外,如果您的代码中有循环引用,请提供一个类似于 clearReferences() 的方法来取消设置这些对象。顺便说一句,这是在 PHP 5.3 中解决的问题。

如果你有:

class Row

    protected $_table;

    public function __construct($table)
    
        $this->_table = $table;
    


class Table

    protected $_row;

    public function __construct()
    
        $this->_row = new Row($this);
    

向 Row 类添加 clearReferences() 方法:

class Row

    public function clearReferences()
    
        $this->_table = null;
    

这就是我暂时能想到的。

【讨论】:

以上是关于限制 PHP 脚本的建议/技巧的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 上传图片并达到脚本内存限制

php调用shell的方法技巧

php脚本执行时间限制

PHP 将脚本执行的PHP时间限制设置为无穷大

如何限制使用 PHP 将 JavaScript 脚本插入数据库?

PHP教程-防止网站被刷票的小技巧