PHP Daemon/worker environment

后端 未结 5 701
一个人的身影
一个人的身影 2020-12-07 16:02

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

5条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-07 16:40

    Bellow is our working implementation of @chaos answer. Code to handle signals was removed as this script lives usually just few milliseconds.

    Also, in code we added 2 functions to save pids between calls: restore_processors_state() and save_processors_state(). We've used redis there, but you can decide to use implementation on files.

    We run this script every minute using cron. Cron checks if all processes alive. If not - it re-run them and then dies. If we want to kill existing processes then we simply run this script with argument kill: php script.php kill.

    Very handy way of running workers without injecting scripts into init.d.

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

提交回复
热议问题