php 如何运行一个长寿命的后台进程,linux服务器

rseugnpd  于 2023-02-28  发布在  PHP
关注(0)|答案(2)|浏览(138)

我正在运行一个webapp(php),需要处理一些“繁重”的任务(从30秒到3分钟)。我知道这不是特别繁重,但我不能让我的用户等待它们,所以我设置了一个内部API,如下所示:http://localhost/process-picture/745884/,我将此操作存储在MySQL表中。
现在,我想创建一个“进程”,它获取MySQL表并执行队列中最早的操作,一旦完成,它就执行下一个操作,依此类推。
首先,我想制作一个PHP脚本,通过cURL调用系统,如下所示:
fetchOperation.php连接到DB并获取操作的URL以通过cURL调用它。执行自身,然后从队列中删除自身并再次调用(cURL)fetchOperation.php
我觉得这个系统有点棘手,所以我想知道是否有办法(以及用哪种语言编写)设置一个后台进程,每15秒检查一次DB,并执行以下操作:

  • 删除标记为DONE的所有行。
  • 检查是否有任何行标记为PROCESSING,如果有,只需退出并等待下一个15秒。
  • 如果没有PROCESSING行,则触发最旧的PENDING行(FIFO队列)。

通过这种方式,我可以随时管理正在处理的内容,甚至控制服务器负载(例如,在晚上允许最多有三个PROCESSING项)。
抱歉解释这么久,先谢谢你!

vnjpjtjt

vnjpjtjt1#

听起来您需要使用x1e0 f1 a来调度作业。cron将只运行脚本/程序,因此其实现将与调度本身不同。
Cron只会fire/forget,所以你可以从它那里调用任何持续时间的流程(我正在看下面你对执行时间的评论--如果我误解了,请修改)

qnakjoqk

qnakjoqk2#

最后我用这样的方法解决了这个问题:
1.以url可调用的方式设计操作。例如:http://localhost/render-image/14523665
2.将挂起的操作存储在一个表中,如下所示:操作(操作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_operationOperationsQueue类)执行以下操作(注意,它尚未实现):

<?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';
    }

}

我想它可能对其他人有用如你所见,它将操作链起来。

相关问题