PHP Daemon / işçi ortamı

5 Cevap php

Problem: I want to implement several php-worker processes who are listening on a MQ-server queue for asynchronous jobs. The problem now is that simply running this processes as daemons on a server doesn't really give me any level of control over the instances (Load, Status, locked up)...except maybe for dumping ps -aux. Because of that I'm looking for a runtime environment of some kind that lets me monitor and control the instances, either on system (process) level or on a higher layer (some kind of Java-style appserver)

Herhangi bir işaretçiler?

5 Cevap

İşte yararlı olabilir bazı kod.

<?
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();
?>

Aslında sürekli çalışıyor olması gerekir mi?

Eğer sadece istek üzerine yeni bir işlem spawn istiyorsanız, xinetd'de bir hizmet olarak kayıt edebilirsiniz.

Zaten bir * nix sistem üzerinde çalışan ve sadece işçileri yönetmek için bir yol istediğiniz bir MQ var gibi geliyor.

Bunu yapmak için çok basit bir yolu GNU ekran kullanmaktır. Kullanabilirsiniz 10 işçi başlatmak için:

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

Bu worker_1 adında ekranlar, böylece 2,3 ve kullanarak arka planda 10 işçi başlayacak.

Sen ekran-r worker_ çalıştırarak ekranlara yeniden bağlayın ve ekran listesini kullanarak çalışan işçileri listeleyebilirsiniz.

For more info this guide may be of help: http://www.kuro5hin.org/story/2004/3/9/16838/14935

Ayrıca deneyin:

  • ekran - help
  • adam ekranı
  • ya da google.

Üretim sunucuları için ben normalde normal sistem başlatma komut dosyalarını kullanarak tavsiye ederim, ama ben hiçbir sorunları ile yıllarca başlangıç ​​komut dosyalarını ekran komutları çalışan edilmiştir.

PHP için bir PCNTL eklenti tipi sunucu daemon

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

Körük @ kaos cevap bizim çalışma uygulamasıdır. Sinyallerini işlemek için kod bu komut genellikle sadece birkaç milisaniyede yaşıyor olarak çıkarıldı.

Ayrıca, kodu biz çağrıları arasında pids kurtarmak için 2 fonksiyonlar ekledi: restore_processors_state () ve save_processors_state (). Biz redis orada kullanılan, ama dosyalar üzerinde uygulamasını kullanmaya karar verebilirsiniz.

Biz bu komut dosyasını cron kullanarak her dakika çalıştırın. Tüm işlemler hayatta ise Cron denetler. Değilse - onları yeniden çalıştırın ve daha sonra ölür. Biz mevcut süreçleri öldürmek istiyorsanız o zaman sadece argümanı ile bu komut dosyasını çalıştırmak kill: php script.php kill.

Init.d. içine komut enjekte olmadan işçi çalıştıran çok kullanışlı bir yoldur

<?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();