用于限制PHP脚本的建议/技巧

时间:2009-04-15 15:50:55

标签: php cron lamp wamp

我有一个定期运行脚本的计划任务(每小时)。此脚本与数据库和文件系统进行了一些繁重的交互,并且通常需要几分钟才能运行。问题是,当脚本运行时服务器的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特定的答案。在我的情况下,改变托管环境仍然足够早。希望无论操作系统如何,这个问题都会帮助其他人。

9 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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 :(得分:2)

您可以使用nice更改cron条目以启动脚本吗?

答案 4 :(得分:2)

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

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

即使你能成功扼杀分析仪,它也会耗尽宝贵的资源,否则就可以为用户提供服务。

答案 5 :(得分:1)

这可能是一个很难的改变,但值得将数据结构重构为迭代器。此外,如果您的代码中有循环引用,请提供类似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);
    }
}

将一个clearReferences()方法添加到Row类:

class Row
{
    public function clearReferences()
    {
        $this->_table = null;
    }
}

这就是我现在所能想到的一切。

答案 6 :(得分:1)

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

0 * * * *很好-n19 php myscript.php

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

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

答案 7 :(得分:1)

也许你的剧本只是试图一次性做太多。如果每小时运行三次,它会减少吗?

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

另一种看待的方法是,它的工作是否可以分为不同的方向。这些类型的脚本通常有一些大的SQL语句,它们生成用于生成大量小SQL语句的结果。如果后者可以放在某个地方,可以在后面的步骤中对数据库进行操作。这种方法也可能允许您使用无缓冲的查询来获取预处理数据,这可能会大大减少PHP代码的内存消耗。

答案 8 :(得分:0)

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