Как pcntl_fork работает в PHP?

Меня смущает pcntl_fork в PHP.

Я думаю, что это многопоточность, но как это работает и как я могу использовать это в сценарии?


person user1432856    schedule 03.06.2012    source источник
comment
См. stackoverflow.com/q/19546588/632951   -  person Pacerier    schedule 31.08.2015


Ответы (1)


PCNTL не может создавать потоки. Он только «разветвляет» текущий PHP-процесс. Что это означает? Когда вы вызываете pcntl_fork(), текущий процесс разделяется на два процесса. Все пространство имен родительского процесса копируется в дочерний, и оба процесса продолжают выполнение параллельно с одним отличием: pcntl_fork() возвращает PID дочернего процесса в родительском и 0 в дочернем.

Некоторые подсказки:

  • По умолчанию он отключен. Если удастся включить, то сделайте это только для CLI. Никогда не используйте его с веб-сервером! Он будет вести себя недетерминированным образом. Это также может вывести из строя всю машину. Пожалуйста, оставьте его отключенным и читайте дальше.
  • Связь между процессами возможна, но ужасна (через сериализованный объект в общей памяти).
  • Дескрипторы файлов (и соединения с базой данных) являются общими, что очень часто вызывает проблемы. Вы должны повторно подключить свою БД после разветвления, иначе вы получите ошибки типа MySQL server has gone away от всех разветвленных процессов, когда первый из них закроет соединение.
  • Родительский процесс должен ждать завершения дочерних процессов, иначе он оставит процессы-зомби, потребляющие системные ресурсы.

Вот пример из документации:

<?php

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}

Но помните, PHP - это просто язык сценариев. Он не предназначен для параллельных вычислений. Вы могли бы лучше справиться с одновременным запуском CRON, очередей сообщений или программы на языке нижнего уровня, в зависимости от ваших потребностей.

Разветвленную программу PHP очень сложно читать, понимать и отлаживать. Поддерживать эту программу будет кошмаром.

Не делайте ошибок и избегайте разветвлений. Тебе это не нужно. Что вам действительно нужно, так это асинхронный исполнитель задач. Хорошие новости: есть RabbitMQ и хороший учебник ;-) Вы также можете попробовать многообещающую библиотеку RabbitMQ под названием Зайчик

PS: Использование очередей сообщений вместо разветвления дает вам еще одно преимущество. Вы можете обрабатывать очередь с несколькими серверами и масштабировать ее по горизонтали по мере роста вашего трафика.

РЕДАКТИРОВАТЬ 2019-03-07

Я много играл с фреймворком асинхронного параллелизма amphp, и я должен упомянуть об этом здесь. Если вам действительно нужно запускать асинхронные неблокирующие задачи в одном запросе, я считаю amphp лучшим решением на сегодняшний день. Он использует концепцию генераторов php ($value = yield $promise) для выполнения кода, понятного человеку, без адского обещания, подобного responsephp.

https://amphp.org/

person Martin Strouhal    schedule 28.10.2012
comment
Спасибо, ваш ответ мне помог :) - person Mehdi Maghrouni; 26.02.2014
comment
Вы бы порекомендовали создавать демонов с разветвлением? - person Raheel; 22.10.2018
comment
ReactPHP использует разветвление, когда библиотека c не установлена, поэтому убедитесь, что есть простой способ обработать вилку. - person Máxima Alekz; 30.10.2019