Question

Problème: Je veux mettre en œuvre plusieurs processus travailleurs php qui sont à l'écoute sur une file d'attente MQ-serveur pour les tâches asynchrones. Le problème est maintenant que le simple fait d'exécuter ce processus en tant que daemons sur un serveur ne pas vraiment me donner un niveau de contrôle sur les instances (charge, état, verrouillé) ... sauf peut-être pour le dumping ps -aux. À cause de cela, je suis à la recherche d'un environnement d'exécution d'une sorte qui me permet de surveiller et de contrôler les instances, que ce soit au niveau ou sur une couche supérieure (une sorte de serveur d'applications de style Java) système (processus)

Les pointeurs?

Était-ce utile?

La solution

Voici un code qui peut être 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();
?>

Autres conseils

Il semble que vous avez déjà un MQ et en cours d'exécution sur un système * nix et veulent juste une façon de gérer les travailleurs.

Une manière très simple de le faire est d'utiliser l'écran GNU. Pour commencer à 10 travailleurs, vous pouvez utiliser:

#!/bin/sh
for x in `seq 1 10` ; do
screen -dmS worker_$x php /path/to/script.php worker$x
end

Cela va démarrer 10 travailleurs en arrière-plan à l'aide des écrans du nom worker_1,2,3 et ainsi de suite.

Vous pouvez refixer aux écrans en exécutant écran -r worker_ et la liste des travailleurs en cours d'exécution en utilisant -list écran.

Pour plus d'informations ce guide peut être utile: http://www.kuro5hin.org/story/2004/3/ 9/16838/14935

Essayez aussi:

Pour les serveurs de production, je recommande normalement en utilisant les scripts normaux de démarrage du système, mais j'ai été en cours d'exécution des commandes d'écran à partir des scripts de démarrage pendant des années sans problème.

Avez-vous réellement besoin d'être en cours d'exécution en continu?

Si vous ne voulez reproduire nouveau processus sur demande, vous pouvez vous inscrire comme un service xinetd.

un démon serveur de type plugin pcntl pour PHP

http://dev.pedemont.com/sonic/

Bellow est notre implémentation de travail de @chaos réponse. Code pour gérer des signaux a été enlevé comme ce script vit habituellement à quelques millisecondes.

En outre, dans le code nous avons ajouté 2 fonctions pour sauver pid entre les appels: restore_processors_state () et save_processors_state (). Nous avons utilisé redis là-bas, mais vous pouvez décider d'utiliser la mise en œuvre sur les fichiers.

Nous courons ce script toutes les minutes en utilisant Cron. Cron vérifie si tous les processus vivants. Dans le cas contraire - il les re-courir et puis meurt. Si nous voulons tuer les processus existants, nous courons simplement ce script avec l'argument kill:. php script.php kill

Manière très pratique des travailleurs en cours d'exécution sans injecter des scripts dans 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();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top