问题:我想实现几个正在MQ服务器队列上侦听异步作业的php工作进程。现在的问题是,简单地在服务器上运行这个进程作为守护进程并不能真正控制实例(负载,状态,锁定)......除了可能用于转储ps -aux。 因此,我正在寻找某种允许我监视和控制实例的运行时环境,无论是在系统(进程)级还是在更高层(某种Java风格的应用服务器)上,都可以监视和控制这些实例。PHP守护进程/工作环境
任何指针?
问题:我想实现几个正在MQ服务器队列上侦听异步作业的php工作进程。现在的问题是,简单地在服务器上运行这个进程作为守护进程并不能真正控制实例(负载,状态,锁定)......除了可能用于转储ps -aux。 因此,我正在寻找某种允许我监视和控制实例的运行时环境,无论是在系统(进程)级还是在更高层(某种Java风格的应用服务器)上,都可以监视和控制这些实例。PHP守护进程/工作环境
任何指针?
下面是一些可能有用的代码。
<?
define('WANT_PROCESSORS', 5);
define('PROCESSOR_EXECUTABLE', '/path/to/your/processor');
set_time_limit(0);
$cycles = 0;
$run = true;
$reload = false;
declare(ticks = 30);
function signal_handler($signal) {
switch($signal) {
case SIGTERM :
global $run;
$run = false;
break;
case SIGHUP :
global $reload;
$reload = true;
break;
}
}
pcntl_signal(SIGTERM, 'signal_handler');
pcntl_signal(SIGHUP, 'signal_handler');
function spawn_processor() {
$pid = pcntl_fork();
if($pid) {
global $processors;
$processors[] = $pid;
} else {
if(posix_setsid() == -1)
die("Forked process could not detach from terminal\n");
fclose(stdin);
fclose(stdout);
fclose(stderr);
pcntl_exec(PROCESSOR_EXECUTABLE);
die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n");
}
}
function spawn_processors() {
global $processors;
if($processors)
kill_processors();
$processors = array();
for($ix = 0; $ix < WANT_PROCESSORS; $ix++)
spawn_processor();
}
function kill_processors() {
global $processors;
foreach($processors as $processor)
posix_kill($processor, SIGTERM);
foreach($processors as $processor)
pcntl_waitpid($processor);
unset($processors);
}
function check_processors() {
global $processors;
$valid = array();
foreach($processors as $processor) {
pcntl_waitpid($processor, $status, WNOHANG);
if(posix_getsid($processor))
$valid[] = $processor;
}
$processors = $valid;
if(count($processors) > WANT_PROCESSORS) {
for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--)
posix_kill($processors[$ix], SIGTERM);
for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--)
pcntl_waitpid($processors[$ix]);
} elseif(count($processors) < WANT_PROCESSORS) {
for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++)
spawn_processor();
}
}
spawn_processors();
while($run) {
$cycles++;
if($reload) {
$reload = false;
kill_processors();
spawn_processors();
} else {
check_processors();
}
usleep(150000);
}
kill_processors();
pcntl_wait();
?>
您是否确实需要它持续运行?
如果您只想根据请求产生新进程,则可以在xinetd中将其注册为服务。
这听起来像你已经有一个MQ并运行在* nix系统上,只是想要一种管理工人的方法。
一个非常简单的方法是使用GNU屏幕。要启动10个工人,您可以使用:
#!/bin/sh
for x in `seq 1 10` ; do
screen -dmS worker_$x php /path/to/script.php worker$x
end
这将使用名为worker_1,2,3等屏幕在后台启动10名工人。
您可以通过运行screen -r worker_并通过使用screen -list列出正在运行的工作人员来重新附加到屏幕。
欲了解更多信息本指南可能会有所帮助: http://www.kuro5hin.org/story/2004/3/9/16838/14935
相关搜索:
对于生产服务器,我通常会推荐使用正常的系统启动脚本,但我一直在运行启动脚本的屏幕命令多年,没有任何问题。
贝娄是我们@chaos答案的工作实施了pcntl插件类型的服务器守护程序。处理信号的代码被删除,因为这个脚本通常只有几毫秒。此外,在代码中,我们添加了2个函数来保存调用之间的pid:restore_processors_state()和save_processors_state()。我们在那里使用了redis
,但是您可以决定在文件上使用实现。
我们使用cron每分钟运行一次该脚本。 Cron检查是否所有进程都活着。如果不是,它会重新运行它们然后死亡。如果我们想要杀死现有进程,那么我们只需运行参数kill
:php script.php kill
即可运行此脚本。
非常方便的方式运行工作人员没有注入脚本到init.d.
<?php
include_once dirname(__FILE__) . '/path/to/bootstrap.php';
define('WANT_PROCESSORS', 5);
define('PROCESSOR_EXECUTABLE', '' . dirname(__FILE__) . '/path/to/worker.php');
set_time_limit(0);
$run = true;
$reload = false;
declare(ticks = 30);
function restore_processors_state()
{
global $processors;
$redis = Zend_Registry::get('redis');
$pids = $redis->hget('worker_procs', 'pids');
if(!$pids)
{
$processors = array();
}
else
{
$processors = json_decode($pids, true);
}
}
function save_processors_state()
{
global $processors;
$redis = Zend_Registry::get('redis');
$redis->hset('worker_procs', 'pids', json_encode($processors));
}
function spawn_processor() {
$pid = pcntl_fork();
if($pid) {
global $processors;
$processors[] = $pid;
} else {
if(posix_setsid() == -1)
die("Forked process could not detach from terminal\n");
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
pcntl_exec('/usr/bin/php', array(PROCESSOR_EXECUTABLE));
die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n");
}
}
function spawn_processors() {
restore_processors_state();
check_processors();
save_processors_state();
}
function kill_processors() {
global $processors;
foreach($processors as $processor)
posix_kill($processor, SIGTERM);
foreach($processors as $processor)
pcntl_waitpid($processor, $trash);
unset($processors);
}
function check_processors() {
global $processors;
$valid = array();
foreach($processors as $processor) {
pcntl_waitpid($processor, $status, WNOHANG);
if(posix_getsid($processor))
$valid[] = $processor;
}
$processors = $valid;
if(count($processors) > WANT_PROCESSORS) {
for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--)
posix_kill($processors[$ix], SIGTERM);
for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--)
pcntl_waitpid($processors[$ix], $trash);
}
elseif(count($processors) < WANT_PROCESSORS) {
for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++)
spawn_processor();
}
}
if(isset($argv) && count($argv) > 1) {
if($argv[1] == 'kill') {
restore_processors_state();
kill_processors();
save_processors_state();
exit(0);
}
}
spawn_processors();
另请参阅:http://symfony.com/doc/master/components/process.html – 2012-07-06 22:02:15