简而言之:我希望在Gearman客户端中调用runTasks()
的总时间超时。
我觉得自己不能成为第一个想要这个的人,但我找不到如何把它放在一起的例子。
这就是我想要实现的目标:
使用PHP GearmanClient的addTask()和runTasks()方法,要求1和2很简单,但这会阻止所有提交的作业完成,所以不符合要求3。
以下是我迄今为止尝试过的一些方法:
runTasks()
与使用setTaskBackground()
而不是{{1}不同}}。我已经看到回复通信的建议可能只是使用不同的机制,比如共享数据存储,但在这种情况下,我不妨放弃Gearman并使用RabbitMQ构建自定义解决方案。
答案 0 :(得分:0)
我认为我找到了一个可行的解决方案,尽管我仍然对替代方案感兴趣。
关键是在I / O超时后再次调用runTasks()
继续等待先前的同步任务,因此您可以从这些部分构建轮询循环:
addTask()
设置的同步,并行任务。setCompleteCallback()
设置的完成回调设置,用于跟踪已完成的任务以及尚未处理的任务数。setTimeout()
的低I / O超时,作为您的轮询频率。runTasks()
,在完成所有任务或达到总体超时时退出。这也可能有更复杂的退出条件,例如“在N秒之后,或至少X结果”等等。最大的缺点是超时会发出PHP警告,因此您必须使用自定义错误处理程序或@
运算符来压缩它。
这是一个经过充分测试的例子:
// How long should we wait each time around the polling loop if nothing happens
define('LOOP_WAIT_MS', 100);
// How long in total should we wait for responses before giving up
define('TOTAL_TIMEOUT_MS', 5000);
$client= new GearmanClient();
$client->addServer();
// This will fire as each job completes.
// In real code, this would save the data for later processing,
// as well as tracking which jobs were completed, tracked here with a simple counter.
$client->setCompleteCallback(function(GearmanTask $task) use (&$pending) {
$pending--;
echo "Complete!\n";
echo $task->data();
});
// This array can be used to track the tasks created. This example just counts them.
$tasks = [];
// Sample tasks; the workers sleep for specified number of seconds before returning some data.
$tasks[] = $client->addTask('wait', '2');
$tasks[] = $client->addTask('wait', '2');
$tasks[] = $client->addTask('wait', '2');
$tasks[] = $client->addTask('wait', '2');
$tasks[] = $client->addTask('wait', '2');
$tasks[] = $client->addTask('wait', '2');
$pending = count($tasks);
// This is the key polling loop; runTasks() here acts as "wait for a notification from the server"
$client->setTimeout(LOOP_WAIT_MS);
$start = microtime(true);
do {
// This will abort with a PHP Warning if no data is received in LOOP_WAIT_MS milliseconds
// We ignore the warning, and try again, unless we've reached our overall time limit
@$client->runTasks();
} while (
// Exit the loop once we run out of time
microtime(true) - $start < TOTAL_TIMEOUT_MS / 1000
// Additional loop exit if all tasks have been completed
// This counter is decremented in the complete callback
&& $pending > 0
);
echo "Finished with $pending tasks unprocessed.\n";
答案 1 :(得分:0)
您的用例听起来就像为CAN_DO_TIMEOUT创建的那样:
CAN_DO_TIMEOUT
Same as CAN_DO, but with a timeout value on how long the job is allowed to run. After the timeout value, the job server will mark the job as failed and notify any listening clients. Arguments: - NULL byte terminated Function name. - Timeout value.
因此,对于任何(Worker,Function)元组,您可以定义Worker处理作业的最长时间,否则它将被丢弃。
不幸的是,C服务器中似乎有bug,其中超时在1000秒时被硬编码。
一种解决方法是,如果您能够在gearman之外实现超时逻辑。例如,如果您使用卷曲,肥皂,插座等,通常可以通过调整这些设置来达到预期的效果。