我正在开发一个 PHP 脚本,它是一个工作人员;它的主要任务是检查数据库表中是否有新作业,如果有,则对其采取行动。但是工作会突然出现,中间有很长的间隙,所以我设计了一个睡眠周期,例如:
while(true) {
if ($jobs = get_new_jobs()) {
// Act upon the jobs
} else {
// No new jobs now
sleep(30);
}
}
很好,但在某些情况下,这意味着在执行新工作之前可能会有 30 秒的延迟。由于这是一个守护进程脚本,我想我应该尝试 pcntl_signal
钩子捕获 SIGUSR1 信号以推动脚本唤醒,例如:
$_isAwake = true;
function user_sig($signo) {
global $_isAwake;
daemon_log("Caught SIGUSR1");
$_isAwake = true;
}
pcntl_signal(SIGUSR1, 'user_sig');
while(true) {
if ($jobs = get_new_jobs()) {
// Act upon the jobs
} else {
// No new jobs now
daemon_log("No new jobs, sleeping...");
$_isAwake = false;
$ts = time();
while(time() < $ts+30) {
sleep(1);
if ($_isAwake) break; // Did a signal happen while we were sleeping? If so, stop sleeping
}
$_isAwake = true;
}
}
我将 sleep(30)
分解为更小的睡眠位,以防出现信号不会中断 sleep()
命令,认为这最多会导致一秒的延迟,但在日志文件中,我看到 SIGUSR1 直到之后才被捕获整整 30 秒已经过去(也许外部 while
循环会重置)。
我找到了 pcntl_signal_dispatch
命令,但这仅适用于 PHP 5.3 及更高版本。如果我使用该版本,我可以在 if ($_isAwake)
调用之前调用该命令,但目前我使用的是 5.2.13。
在什么情况下,PHP 版本中的信号队列会被解释而无法显式调用队列解析?我可以在该睡眠循环中放入其他一些无用的命令来触发其中的信号队列解析吗?
I've got a PHP script in the works that is a job worker; its main task is to check a database table for new jobs, and if there are any, to act on them. But jobs will be coming in in bursts, with long gaps in between, so I devised a sleep cycle like:
while(true) {
if ($jobs = get_new_jobs()) {
// Act upon the jobs
} else {
// No new jobs now
sleep(30);
}
}
Good, but in some cases that means there might be a 30 second lag before a new job is acted upon. Since this is a daemon script, I figured I'd try the pcntl_signal
hook to catch a SIGUSR1 signal to nudge the script to wake up, like:
$_isAwake = true;
function user_sig($signo) {
global $_isAwake;
daemon_log("Caught SIGUSR1");
$_isAwake = true;
}
pcntl_signal(SIGUSR1, 'user_sig');
while(true) {
if ($jobs = get_new_jobs()) {
// Act upon the jobs
} else {
// No new jobs now
daemon_log("No new jobs, sleeping...");
$_isAwake = false;
$ts = time();
while(time() < $ts+30) {
sleep(1);
if ($_isAwake) break; // Did a signal happen while we were sleeping? If so, stop sleeping
}
$_isAwake = true;
}
}
I broke the sleep(30)
up into smaller sleep bits, in case a signal doesn't interrupt a sleep()
command, thinking that this would cause at most a one-second delay, but in the log file, I'm seeing that the SIGUSR1 isn't being caught until after the full 30 seconds has passed (and maybe the outer while
loop resets).
I found the pcntl_signal_dispatch
command, but that's only for PHP 5.3 and higher. If I were using that version, I could stick a call to that command before the if ($_isAwake)
call, but as it currently stands I'm on 5.2.13.
On what sort of situations is the signals queue interpreted in PHP versions without the means to explicitly call the queue parsing? Could I put in some other useless command in that sleep loop that would trigger a signal queue parse within there?
发布评论
评论(1)
解决了我自己的问题:答案是“
Fixed my own problem: The answer is the "ticks" declaration. I had, as part of the Daemon process startup done the
declare(ticks=1);
action, but it wasn't seeming to carry over to the main script (since that was inside a function, in an include file?. Adding adeclare(ticks=1)
line before thewhile(true)
loop causes signals to come through immediately (i.e. thesleep(1)
command causes a tick, so after waking up from sleep, signals are processed).