1

下面是一个例子的代码PHP worker。网络上的所有示例都使用 proc_open() 并打开子进程来完成工作。

Worker.php 与子进程

ini_set('display_errors', 'On');
ini_set('error_reporting', E_ALL);

error_reporting(E_ALL | E_NOTICE | E_STRICT);

function executeWorker($body) {
  // open a php process and call the worker.php script
  $pipes = array();
  $process = proc_open(
    '/usr/bin/php -d display_errors=stderr /var/www/project/worker.php',
    array(
      0 => array("pipe", "r"),
      1 => array("pipe", "w"),
      2 => array("pipe", "w"),
      3 => array("pipe", "r")
    ),
    $pipes,
    sys_get_temp_dir(),
    null
  );

  var_dump($process);

  if (is_resource($process)) {
    // write the message into worker.php stdin
    fwrite($pipes[0], $body);
    fclose($pipes[0]);

    // read errors from worker.php
    $stdErr = stream_get_contents($pipes[2]);
    fwrite($pipes[2], $stdErr);
    fclose($pipes[2]);

    $value = proc_close($process);

    var_dump($value);

    // if worker.php ends without errors, execution was successful
    if ($value === 0 && empty($stdErr)) {
      return true;
    }
  }
  return false;
}

executeWorker('test');

但是使用 php register 错误处理程序,我们可以捕获 php worker 错误,然后我们可以将失败的作业写入数据库。

我的问题是如果我们使用 supervisord 为什么我们需要打开子进程?

例子

Worker.php 没有子进程

Class Worker
{
    public $delay;
    public $memory;
    public $timeout;
    public $sleep;
    public $maxTries;

    public function __construct()
    {
        static::registerExceptionHandler();
        static::registerErrorHandler();
        static::registerFatalErrorHandler();
    }

    public function init() 
    {
        ini_set('error_reporting', 0); // Disable cli errors on console mode we already had error handlers.
        ini_set('display_errors', 0);
                                               // Don't change here we already cathc all errors except the notices.
        error_reporting(E_NOTICE | E_STRICT);  // This is just Enable "Strict Errors" otherwise we couldn't see them.

        $this->memory = (int)$_SERVER['argv'][1];        // Sets maximum allowed memory for current job. Uses php ini_set('memory_limit', 'xM') function.
        $this->delay  = (int)$_SERVER['argv'][2];           // Sets job delay interval
        $this->timeout = (int)$_SERVER['argv'][3];      // Sets time limit execution of the current job. Uses php set_time_limit() function..

        $this->doJob();
    }

    public function doJob()
    {
        // do jobs in here ...
        // $job->new JobClass();
        // $job->release();
    }

    public static function registerErrorHandler($continueNativeHandler = false)
    {
        $previous = set_error_handler(
            function ($level, $message, $file, $line) use ($errorPriorities, $continueNativeHandler) {
                $iniLevel = error_reporting();
                if ($iniLevel & $level) {

                    // echo $message;  write process errors to database
                }
                return ! $continueNativeHandler;
            }
        );
    }

    public function registerExceptionHandler()
    {
        set_exception_handler(
            function ($exception) {
                $messages = array();
                do {
                    $extra = array();
                    if (isset($exception->xdebug_message)) {
                        $extra['xdebug'] = $exception->xdebug_message;
                    }
                    $messages[] = array(
                        'priority' => $priority,
                        'message'  => $exception->getMessage(),
                        'extra'    => $extra,
                    );
                    $exception = $exception->getPrevious();
                } while ($exception);

                foreach (array_reverse($messages) as $message) {
                    // echo $message write failures to database
                }
            }
        );
        return true;
    }

    public static function registerFatalErrorHandler()
    {
        register_shutdown_function(
            function () {
                if (null != $error = error_get_last()) {

                        // Write fatal errors to 
                }
            }
        );
    }

}

// END Worker class

使用主管

vi myMailer.conf

[program:myMailer]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/project/worker.php --memory:128 --delay=0 --timeout=3
numprocs=3
autostart=true
autorestart=true
stdout_logfile=/var/www/project/data/logs/myMailerProcess.log
stdout_logfile_maxbytes=1MB

启动所有工人

supervisorctl start all

myMailer_02: started
myMailer_01: started
myMailer_00: started

myImages_02: started
myImages_01: started
myImages_00: started

然后开始进程

主管

myMailer:myMailer_00           RUNNING    pid 16847, uptime 0:01:41
myMailer:myMailer_01           RUNNING    pid 16846, uptime 0:01:41
myMailer:myMailer_02           RUNNING    pid 16845, uptime 0:01:41

那么为什么我们需要使用 proc_open() 函数呢?

4

0 回答 0