如何运行longlife后台进程,linux服务器
Posted
技术标签:
【中文标题】如何运行longlife后台进程,linux服务器【英文标题】:How to run a longlife background process, linux server 【发布时间】:2012-09-20 03:56:03 【问题描述】:我正在运行一个需要处理一些“繁重工作”任务(从 30 秒到 3 分钟)的 webapp (php)。我知道它不是很重,但我不能让我的用户等待他们,所以我设置了一个内部 API,例如:http://localhost/process-picture/745884/
,并将此操作存储在 mysql 表中。
现在我想创建一个“进程”来获取那个 MySQL 表并执行最早的排队操作,一旦完成,它就会得到下一个,依此类推。
首先我想到了制作一个通过 cURL 调用系统的 PHP 脚本:
fetchOperation.php
连接到 DB 并获取操作的 URL 以通过 cURL 调用它。
每个操作:执行自己,然后从队列中删除自己并再次调用 (cURL) fetchOperation.php
。
我觉得这个系统有点棘手,所以我想知道是否有(以及用哪种语言编写)任何方式来设置每 15 秒检查一次数据库的后台进程,并执行以下操作:
删除所有标记为DONE
的行。
检查是否有任何标记为PROCESSING
的行,如果有,则退出并等待接下来的15秒。
如果没有 PROCESSING
行,则触发最旧的 PENDING
一个(FIFO 队列)。
这样我可以随时管理正在处理的内容,甚至控制服务器负载(例如,晚上最多允许拥有三个PROCESSING
项)。
抱歉解释了这么长,提前谢谢!
【问题讨论】:
提交到队列,并有一个 crontab 来解析队列工作。 这个进程是否必须在没有网络服务器调用的服务器上运行(例如 cron 脚本)? Rows "marked as" 表示有一列包含此信息?您可以在发生这种情况的服务器中编写和运行脚本吗? quinestor,是的,该表很简单:id_operation、url、status ... status 包含以前的值。顺便说一句,我使用的是亚马逊 ec2,所以我可以以 root 身份运行,使用脚本等。 【参考方案1】:听起来您需要使用cron 安排工作。 cron 将只运行一个脚本/程序,因此它的实现将与调度本身不同。
Cron 只会触发/忘记,因此您可以从中调用任何持续时间的进程(我正在查看您在下面的执行时间评论 - 如果我误解了请修改)
【讨论】:
同意。可能需要对 php 执行时间进行额外调整 CLI解释器使用的php.ini
默认没有noch执行时间限制,但是是的:看看$ php -i | grep -i max_execution_time
不会有什么坏处
是的,这可能是一个好方法。所以我只是设置了一个连接到数据库并触发(通过 cURL 请求)我想要的 cron php。对吗?【参考方案2】:
最后我这样解决了:
第一。以可通过 URL 调用的方式设计操作。例如:http://localhost/render-image/14523665
第二。将挂起的操作存储在这样的表中:操作(操作 ID、操作 URL、操作状态)。
准备就绪后,我设计了一个简短的 PHP 脚本,它执行以下操作:
<?php
if( WORKER_IS_ONLINE !== true ) exit();
OperationsQueue::CleanQueue();
while( OperationsQueue::RunningOperations() < WORKER_MAX_OPERATIONS )
launch_operation( OperationsQueue::DequeOperation() );
sleep( WORKER_SLEEP_TIME );
launch_operation( '/operations_queue/deque' );
这个辅助函数(launch_operation
和 OperationsQueue
类)执行如下(注意它尚未实现):
<?php
define('WORKER_SLEEP_TIME', 15); // Time to sleep between sweeps.
define('WORKER_HOST', 'localhost'); // Hostname where the operations will be performed.
define('WORKER_PORT', 80); // Port where the operations will be performed.
define('WORKER_SOCKET_TIMEOUT', 80); // Port where the operations will be performed.
define('WORKER_MAX_OPERATIONS', 2); // Max simultaneous operations.
define('WORKER_MAX_LAUNCHES', 2); // Max operations launched within a sweep.
define('WORKER_IS_ONLINE', false); // Bool value that marks whether the worker must be working or not.
function launch_operation($operation)
$fp = fsockopen(WORKER_HOST, WORKER_PORT, $errno, $errstr, WORKER_SOCKET_TIMEOUT);
if ($fp)
$out = 'GET ' . $operation . " HTTP/1.1\r\n";
$out .= 'Host: ' . WORKER_HOST . "\r\n\r\n";
fwrite($fp, $out);
fclose($fp);
class OperationsQueue
public static function RunningOperations()
// connect to DB an perform: SELECT COUNT(*) FROM operations WHERE status = 'PROCESSING';
return 1;
public static function CleanQueue()
// connect to DB an perform: DELETE FROM operations WHERE status IN ('DONE', 'CANCELED');
public static function DequeOperation()
// connect to DB an perform: SELECT * FROM operations WHERE status = 'PENDING' ORDER BY id ASC LIMIT 0, 1;
// UPDATE operations SET status = 'PROCESSING', tries = tries+1 WHERE id = $id;
return 'operation_url';
我认为它可能对其他人有用。如您所见,它链接了操作。
【讨论】:
如果您的 cron 脚本是 php,并且您通过 url 调用 php 脚本,为什么不将此功能的所有 php 移动到 cron 脚本中,您将摆脱不必要的网络流量(虽然可能很小)。 在执行此操作时,我发现它可能需要在 N 秒内运行,其中 cron 以 N 分钟间隔运行。这让我想到了这个设计。同时它允许我在没有 shell 控制的系统中运行它,否则你无法做到。我正在完善系统,我可能很快会在github上发布它。以上是关于如何运行longlife后台进程,linux服务器的主要内容,如果未能解决你的问题,请参考以下文章