6

我一直没有成功找到这个问题的答案。希望这里有人可以提供帮助。

我有一个 PHP 脚本(具体来说是一个 WordPress 模板),当用户点击它时,它会自动导入和处理图像。问题是图像处理占用了大量内存,特别是如果多个用户同时访问模板并启动图像处理。我的服务器因此多次崩溃。

我对此的解决方案是,如果图像处理功能已经在运行,则不执行它。在函数开始运行之前,我会检查一个名为 image_import_running 的数据库条目,看看它是否设置为 false。如果是,则该函数运行。该函数所做的第一件事就是将 image_import_running 设置为 true。然后,在全部完成后,我将其设置回 false。

它工作得很好——理论上。从那以后网站就没有崩溃过,我可以告诉你。但它有两个主要问题:

  1. 如果用户在加载页面时关闭页面,则脚本永远不会完成图像处理,因此永远不会将 image_import_running 设置回 false。在手动设置为 false 之前,模板将永远不会再次处理图像。

  2. 如果脚本在处理图像时超时——如果队列中有很多图像,这很有可能——你会遇到与第 1 号基本相同的问题:脚本永远不会到达将 image_import_running 设置回的点错误的。

为了处理第一个问题(我意识到的两个问题中的第一个),我添加ignore_user_abort(true)到脚本中。它奏效了吗?我不知道,因为 2 号仍然是个问题。这就是我难住的地方。

如果我可以询问服务器脚本是否正在运行,我可以这样做:

if($import_running && $script_not_running) {
    $import_running = false;
}

但是如何设置该$script_not_running变量?打败我。

我已经与您分享了整个故事,以防您有其他出色的解决方案。

4

7 回答 7

1

我宁愿将作业存储到数据库中,将其标记为待处理,并设置一个 cron 作业来一次执行处理一个作业。

于 2013-11-22T16:06:17.983 回答
1

ignore_user_abort(true);即使该人离开并关闭浏览器,尝试使用 它也会继续运行。

您可能还想在 db 记录中放置一个数字而不是 true false 并设置可以一起运行的最大进程数

于 2013-08-08T03:59:39.403 回答
1

设置一个带有过期时间的瞬态会限制操作怎么办?

if(!get_transient( 'import_running' )) {
  set_transient( 'import_running', true, 30 ); // set a 30 second transient on the import.
  run_the_import_function();
}
于 2013-09-20T17:27:08.683 回答
1

正如其他人所建议的那样,最好将图像处理移出请求本身。

image_import_running作为临时“修复”,在处理作业开始时存储时间戳(例如, image_import_commenced)。这是一种非常粗略的机制,但是如果您知道作业在超时之前可以运行的最长时间,脚本可以检查该时间段是否已过。

例如,如果image_import_running仍然为真,但当前时间已超过 10 分钟image_import_commenced,则无论如何运行处理。

于 2013-08-08T10:27:29.970 回答
0

对于我来说,我只是将这个简单的想法与文本文档一起使用。例如
顶部脚本中的 run.txt 文件使用:

if((file_get_contents('run.txt') != 'run'){ // here the script will work
$file = fopen('run.txt', 'w+');
fwrite($file, 'run');
fclose('run.txt');
}else{
exit(); // if it find 'run' in run.txt the script will stop
}

并将其添加到脚本文件的末尾

$file = fopen('run.txt', 'w+');
fwrite($file, ''); //will delete run word for the next try ;)
fclose('run.txt');

这将通过检查runt.txt内容来检查脚本是否已经工作,
如果运行词存在,run.txt它将不会运行

于 2013-08-08T19:40:23.360 回答
0

运行 cron 绝对是一个更好的解决方案。将 url 存储在表格中的想法是一个好主意。

要回答最初的问题,您可以使用 exec 运行 ps auxwww 命令(查看此页面:如何使用 PHP exec() 获取正在运行的 php 脚本列表?)并将您的函数移动到单独的 php 文件中。

exec("ps auxwww|grep myfunction.php|grep -v grep", $output);
于 2013-08-30T07:14:56.063 回答
-2

只需在脚本顶部添加以下内容。

<?php
    // Ensures single instance of script run at a time.
    $fileName = basename(__FILE__);
    $output = shell_exec("ps -ef | grep -v grep | grep $fileName | wc -l");
    //echo $output; 
    if ($output > 2)
    {
        echo "Already running - $fileName\n";
        exit;   
    }

    // Your php script code.
?>
于 2016-09-28T06:53:41.687 回答