Глобальный лимит появления процесса в PHP?

У меня есть PHP-скрипт, который я запускаю на Linux-машине Ubuntu. Сценарий порождает несколько процессов с помощью функции pcntl_fork() и использует функцию pcntl_waitpid() для регистрации их уничтожения. Он порождает эти ОЧЕНЬ часто (по моим оценкам, около 40-50 в секунду), но каждый из этих процессов немедленно завершается (я пробовал и exit(), и posix_kill(${pid}, SIGKILL), но безрезультатно) . Скрипт работает нормально несколько секунд (в зависимости от 10 ~ 30 секунд), но неизбежно останавливается и перестает создавать «дочерние» процессы. Использование памяти на машине из-за сценария не увеличивается, но когда сценарий останавливается, процессор на машине медленно набирает обороты, пока я не принудительно завершу сценарий с помощью Ctrl-C. Каждый процесс предназначен для анализа строки текста и, наконец, сохранения ее в файл. В целях тестирования я просто выхожу из дочерних процессов, как только они создаются. В одном тесте около 1400 процессов были успешно запущены и остановлены до того, как скрипт завис, хотя, как я уже сказал, это диапазон.

Я понимаю, что у машины есть ulimit, но я полагаю, что читал, что он ограничивает количество одновременных процессов. Поскольку этот сценарий убивает дочерние процессы сразу после их создания, я не понимаю, что происходит. Вот результат моей текущей конфигурации ulimit (ulimit -a):

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 29470
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 29470
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Есть ли в PHP глобальный лимит, определяющий общее количество процессов, созданных во время выполнения скрипта? ** Имейте в виду, что эти дочерние процессы уничтожаются немедленно, поэтому я не верю, что это проблема создания неограниченного количества процессов, которые крадут системные ресурсы.

Вот исходный код:

Я инициализирую вилку этим

$this->process_control->fork(array($this, "${FUNCTION_NAME}"), array(STRING_LINE), false);

Функция разветвления процесса. В этом случае $ callback - это имя функции, вызываемой в соответствующем классе. $ params - это массив параметров для передачи функции, указанной в $ callback.


    public function fork ($callback, $params = null, $hang = true)
   {

    $this->logger->write_log('log', "Entered fork function!");

            // Evaluate the return value of the fork
        switch ($pid = pcntl_fork()) {
            case -1: // Failed
                $this->logger->write_log('error', "Could not fork!");
                exit(1);
            break;
            case 0: // Child created succesfully

                $this->logger->write_log('log', "Entered child function!");

                $this->logger->write_log('log', 'child ' . posix_getpid() . ' started');
                if (empty($callback)) {
                   $this->logger->write_log('warn', "Callback empty, nothing to do!");
                   exit(1);
                }

                if (is_array($callback) && is_array($params)) {
                    if (!call_user_func_array($callback, $params)) {
                        $this->logger->write_log('error', "Daemonized process returned false!");
                        exit(1);
                    } else {
                        exit(0);
                    }
                } else {
                    if (!call_user_func($callback, $params)) {
                        $this->logger->write_log('error', "Daemonized process returned false!");
                        exit(1);
                    } else {
                        exit(0);
                    }
                }
                break;

            default: // Parent
                $this->logger->write_log('log', "Entered parent function!");
                if ($hang != true) {
                    $this->wait($pid, false);
                } else {
                    $this->wait($pid);
                }
                break;
           }
    }

    public function wait($p_id, $hang = true)
    {
        if ($hang) {
            $pid = pcntl_waitpid($p_id, $status);
        } else {
            $pid = pcntl_waitpid($p_id, $status, WNOHANG);
        }
        switch($pid) {
        case -1:
        case 0:
            $this->logger->write_log('log', "child exited");
            break;
        default:
            $this->logger->write_log('log', "child $pid exited");
            break;
        }
    }

Функция, которая фактически обрабатывает строки текста. Строки текста являются объектами JSON:

public function FUNCTION_NAME($line) {

        $this->logger->write_log('info', 'entered FUNCTION_NAME function');

        $start_time = microtime(true);

        try {
            # check to see that the JSON line is not malformed
            $line_array = json_decode($line, true);
            if (!isset($line_array)) {
                throw new Exception('Could not successfully process line');
            }
            # save the contents to disk
            if (!file_put_contents(FILE_NAME, $line, LOCK_EX)) {
                throw new Exception('file could not be saved');
            }
            $this->logger->write_log('info', 'saved line');
            return true;
        } catch (Exception $e) {
            $this->logger->write_log('error', $e->getMessage());
            $this->logger->write_log('error', '----------------------------------------------------');
            $this->logger->write_log('error', var_export($line, true));
            $this->logger->write_log('error', '----------------------------------------------------');
            file_put_contents(ERROR_SRC_FILE, $line, FILE_APPEND);
            return false;
        }
    }

Извините, если кода слишком много, дайте мне знать о любых вопросах


person iralls    schedule 16.04.2012    source источник
comment
Each process is meant to parse a line of text and finally save it to a file - для меня это не похоже на то, что требует совершенно нового процесса, почему вы думаете, что это способ сделать это?   -  person DaveRandom    schedule 16.04.2012
comment
Возможно, будет уместно опубликовать часть вашего кода, родителей и детей.   -  person netcoder    schedule 16.04.2012
comment
@DaveRandom: сценарий в целом анализирует текстовый поток, который я инициализирую с помощью curl. У меня возникли трудности с анализом потока достаточно быстро, поскольку я объединил процессы извлечения потока и синтаксического анализа / сохранения асинхронным образом. Другими словами, когда я обрабатывал поток, когда он был отправлен по сети, обработка потока занимала слишком много времени, и текстовый поток копировался в очередь. Источник, из которого я получаю поток, имеет ограничение на эту резервную копию. Я решил убрать функцию синтаксического анализа из процесса потоковой передачи в надежде, что это займет меньше времени.   -  person iralls    schedule 16.04.2012
comment
Если вам нужно выполнять параллельный синтаксический анализ, НЕ используйте php. Он никогда не предназначался для многопоточности и, вероятно, никогда не будет.   -  person Marc B    schedule 16.04.2012
comment
@MarcB: Да, я понял это. К сожалению, у меня нет возможности или времени начать с другого языка.   -  person iralls    schedule 16.04.2012
comment
@ rallsi23 Если вы веб-разработчик и хоть что-нибудь знаете о Javascript, то Node.js может вам помочь. Есть много вещей, для которых Node не подходит, но это то, где он, вероятно, будет хорошо работать. В качестве альтернативы вы можете передать синтаксический анализ другому процессу, который вы начинаете с popen() или proc_open(), и передать данные другому процессу STDIN. Вы можете передать этот канал прямо в cURL, и тогда буферизация будет выполняться на вашей стороне, а не на удаленном сервере. Это очень долгий процесс / поток?   -  person DaveRandom    schedule 16.04.2012
comment
@DaveRandom Спасибо за информацию. Я займусь этим. Да, это будет непрерывный процесс, 24 часа в сутки, 7 дней в неделю. Я знаю базовый JavaScript, но одна из причин, по которой я использую PHP, - это единообразие. Подобные проекты в моей компании были написаны на PHP, и они предпочли бы PHP, поскольку больше людей могут устранять неполадки.   -  person iralls    schedule 16.04.2012
comment
Читая ваш код, похоже, что узкое место здесь связано с json_decode(), а также похоже, что вы на самом деле ничего не делаете с данными в PHP-скрипте, просто проверяете его на синтаксически правильный JSON. В этом случае я полагаю, что Node будет лучшим инструментом для работы, поскольку он основан на Javascript и, следовательно, (я бы подумал) должен быть лучше / эффективнее при синтаксическом анализе JSON. Он также спроектирован так, чтобы быть асинхронным, поэтому он намного лучше подходит для этой задачи, чем PHP.   -  person DaveRandom    schedule 16.04.2012
comment
Поскольку вы вызываете pcntl_waitpid с помощью WNOHANG без какого-либо цикла для проверки после первого вызова, уверены ли вы, что процессы не находятся в состоянии зомби? Даже если вы exit от ребенка, родитель все равно должен очистить зомби-процессы после их завершения, что, похоже, не так, если $hang не true.   -  person netcoder    schedule 16.04.2012
comment
@all Спасибо за помощь. Я считаю, что, возможно, дело не в том, что был достигнут «предел» процесса, а в том, что информация, которую я получал из потока, была отключена, по сути, убивая родительский процесс, останавливая дальнейшее выполнение. Я убрал часть обработки, которая, похоже, помогла. У меня все еще есть некоторые проблемы, но я знаю, что это не проблема создания процесса PHP, а проблема приема потока.   -  person iralls    schedule 18.04.2012
comment
@netcoder Спасибо за подсказку. На самом деле я не передаю параметр для использования WNOHANG, это просто вариант, который я оставил для тестирования.   -  person iralls    schedule 18.04.2012


Ответы (1)


Чтобы ответить на исходный вопрос, я не обнаружил, что существует ограничение на количество процессов, которые могут быть созданы с помощью php, при условии, что они будут уничтожены вскоре после их создания. Я считаю, что существует предел процессов, который пользователь может создать в Linux, который можно установить с помощью ulimit.

person iralls    schedule 18.04.2012