7

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

4

9 回答 9

8

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

于 2009-04-15T16:02:39.307 回答
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 情况(活动连接?)

于 2009-04-16T01:27:11.977 回答
3

您可以将 Windows 中的进程设置为较低的优先级。我不确定该进程是如何启动的,但是如果您将进程设置为低优先级,那么如果您将优先级设置为非常低,那么任何想要 CPU 资源的东西都会得到它们。

于 2009-04-15T16:00:23.417 回答
2

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

于 2009-04-15T16:07:49.827 回答
2

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

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

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

于 2009-04-15T16:09:51.490 回答
1

也许您的脚本只是试图一次做太多事情。如果每小时跑三趟,它会不会做得更少?

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

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

于 2009-04-17T04:55:51.903 回答
1

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

0 * * * * 不错 -n19 php myscript.php

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

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

于 2009-04-15T16:20:59.297 回答
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);
    }
}

向 Row 类添加 clearReferences() 方法:

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

这就是我暂时能想到的。

于 2009-04-15T15:59:39.097 回答
0

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

于 2009-04-15T16:00:56.863 回答