我正在运行一个需要处理一些“繁重工作”任务(从30秒到3分钟)的webapp(php)。我知道它不是很重,但我不能让我的用户等待它们,所以我设置了一个内部API,如:http://localhost/process-picture/745884/
,我将此操作存储在MySQL表中。
现在我想创建一个“进程”来获取MySQL表并执行最早的排队操作,一旦完成,就会获得下一个,依此类推。
首先,我考虑制作一个PHP脚本,通过cURL调用系统:
fetchOperation.php
连接到DB并获取操作的URL以通过cURL调用它。
每个操作:执行自身,然后从队列中删除自己并再次调用(cURL)fetchOperation.php
。
我觉得这个系统有点棘手,所以我想知道是否有(以及使用哪种语言编写)以任何方式设置每15秒检查一次数据库的后台进程,并执行以下操作: / p>
DONE
的所有行。PROCESSING
的行,如果是,请退出并等待接下来的15秒。PROCESSING
行,则触发最早的PENDING
行(FIFO队列)。通过这种方式,我可以随时管理正在处理的内容,甚至可以控制服务器负载(例如,在晚上允许最多包含三个PROCESSING
个项目。)
很抱歉这么长的解释,并提前感谢!
答案 0 :(得分:4)
听起来你需要安排cron的工作。 cron将只运行一个脚本/程序,因此它的实现将与调度本身不同。
Cron会解雇/忘记,所以你可以从中调用任何持续时间的进程(我正在查看下面的执行时间评论 - 如果我误解了请修改)
答案 1 :(得分:0)
最后我解决了这个问题:
第一。以可以调用url的方式设计操作。例如:http://localhost/render-image/14523665
第二。将暂挂操作存储在如下表中:operations(opertation-id,operation-url,operation-status)。
一旦准备就绪,我设计了一个简短的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';
}
}
我认为这可能对其他人有用。如你所见,它将操作链接起来。