PHP Daemon / ambiente operaio
-
09-09-2019 - |
Domanda
Problema: Voglio realizzare diversi processi php-lavoratori che stanno ascoltando su una coda MQ-server per job asincroni. Il problema ora è che semplicemente l'esecuzione di questo elabora come demoni in un server in realtà non mi danno nessun livello di controllo sui casi (Load, Stato, rinchiusi) ... tranne forse per il dumping ps -aux. A causa di ciò che sto cercando un ambiente runtime di qualche tipo che mi permette di monitorare e controllare le istanze, sia a livello di sistema (processo) o su un livello superiore (una sorta di appserver in stile Java)
Tutti gli indicatori?
Soluzione
Ecco un po 'di codice che può essere utile.
<?
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();
?>
Altri suggerimenti
Sembra che hai già un MQ installato e funzionante su un sistema * nix e vogliono solo un modo per gestire i lavoratori.
Un modo molto semplice per farlo è quello di utilizzare lo schermo GNU. Per iniziare a 10 lavoratori è possibile utilizzare:
#!/bin/sh
for x in `seq 1 10` ; do
screen -dmS worker_$x php /path/to/script.php worker$x
end
Questo avrà inizio 10 lavoratori in background utilizzando schermi di nome worker_1,2,3 e così via.
È possibile ricollegare alle schermate eseguendo screen -r worker_ ed elencare i lavoratori che eseguono utilizzando -list schermo.
Per ulteriori informazioni questa guida può essere di aiuto: http://www.kuro5hin.org/story/2004/3/ 9/16838/14935
Ricerche correlate:
- schermo --help
- schermo man
- google .
Per i server di produzione che normalmente consiglia di utilizzare i normali script di avvio del sistema, ma mi è stato l'esecuzione di comandi dello schermo da script di avvio per anni senza problemi.
Avete veramente bisogno di essere continuamente in esecuzione?
Se si desidera solo per deporre le uova nuovo processo, su richiesta, è possibile registrare come servizio in xinetd.
un tipo di server daemon PCNTL plug-in per PHP
Qui in basso è la nostra implementazione di lavoro del @chaos risposta. Codice per gestire segnali è stato rimosso come questo script vive di solito solo pochi millisecondi.
Inoltre, nel codice che abbiamo aggiunto 2 funzioni per salvare PID tra le chiamate: restore_processors_state () e save_processors_state (). Abbiamo utilizzato redis
lì, ma si può decidere di usare l'esecuzione sui file.
Noi usiamo questo script ogni minuto usando cron. Cron controlla se tutti i processi in vita. In caso contrario - li ri-correre e poi muore. Se vogliamo uccidere i processi esistenti, allora abbiamo semplicemente eseguire lo script con l'argomento kill
:. php script.php kill
modo molto pratico di gestire lavoratori senza iniettare script in 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();