php ветвление процессов

103
04 мая 2021, 03:20

как на php разветвить процесс так чтобы родительский процесс не дожидался завершения дочерних. Тестирую на винде, запускаю рабочий на убунту. Для примера

echo '<div>2 процесса</div>';
sleep(50);

так чтобы сервер отдал <div>2 процесса</div> моментально, а другой процесс выполнял sleep(50); В дальнейшем в диве будет прогресс бар и эта страница будет общаться со скриптом sleep(50); через вебсокеты и конечно же будет выполняться не 50 секунд, а полчаса или даже час

Answer 1

Вариант скрипта, который по запросу клиента запускает, продолжительные по времени, вычисления и возвращает ответ не дожидаясь их окончания.

При запросе проверяется текущее состояние вычислений. Если, в рамках текущей сессии, вычислений еще не было, то клиенту возращается ответ с информацией о начале таких вычислений, соединение закрывается и вычисления начинают выполняться.

После выполнения вычислений состояние изменяется на выполненное.

На все запросы, которые приходят во время выполнения вычислений и после их завершения - возвращается информация о их текущем состоянии.

<?php
session_start();
if (!isset($_SESSION['status'])) {
    $curStatus = "started";
    $_SESSION['status'] = false;
} elseif (!$_SESSION['status']) {
    $curStatus = "In progress... " . (time() - $_SESSION['started']) . "secs";
} else {
    $curStatus = "finished";
}
if ($curStatus == "started") {
    $_SESSION['started'] = time();
    // Возвращаем ответ и закрываем соединение клиенту -->
    @ob_clean();
    ignore_user_abort(true);
    set_time_limit(0);
    session_write_close(); // закрыть сессию, чтобы снять с нее блокировку и не блочить выполнение скриптов, также использующих ее
    //
    // Этот блок нужен только для того, чтобы не вызывался php_session_send_cookie(),
    // во время будущего второго вызова ф-ии session_start(),
    // т.к. заголовки уже были отправлены во время ее первого вызова  --->
    //
    ini_set('session.use_only_cookies', false);
    ini_set('session.use_cookies', false);
    ini_set('session.use_trans_sid', false);
    ini_set('session.cache_limiter', null);
    // <---
    echo $curStatus;
    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    @ob_end_flush();
    @ob_flush();
    flush();
    fastcgi_finish_request(); // <-- Если используется SAPI FPM
    // <---
    // Начинаем выполнение продолжительных вычислений --->
    sleep(60);
    // <---
    session_start(); // открыть снова сессию и записать в нее "результат вычислений"
    $_SESSION['status'] = true;
} else {
    echo $curStatus;
}

Для сохранения состояния вычислений в примере я использовал сессию, поэтому приходится ее освобождать(закрывать) на время вычисления, а после вычислений - открывать снова для записи в нее.

Answer 2

Может быть, если я правильно понял, то тебе можно попробовать потоки: Потоки

Answer 3

Ветвить процесс не надо. Унесите слип в отдельное приложение. В обработчике запуска инициируйте запуск, отвечайте клиенту <div>2 процесса</div> и дело сделано.

Как инициировать запуск обработчика со слипом в отдельном приложении? Надо отправить приложению сообщение, а оно тем временем должно внимательно слушать и получив сообщение стартовать ваш слип.

Можно написать демона на php и отправить ему сообщение в сокет, можно воспользоваться готовыми решениями (например gearman), можно даже просто записать задачу на запуск в файл и по крону читать его скриптом на php, и если там новая задача, то запускать слип.

Вот симпатичная статья про gearman, в которой объясняется схема работы.

READ ALSO
Как сделать один &ldquo;слушатель&rdquo; для разных EditText,

Как сделать один “слушатель” для разных EditText,

Есть два EditText etDay и etMonthЕсть два слушателя для каждого свой:

79
Динамический массив целых чисел

Динамический массив целых чисел

Спроектируйте класс Array

88
Синхронизация папки GoogleDrive

Синхронизация папки GoogleDrive

GoogleDrive для ПК умеет синхронизировать определённую папку, можно ли это настроить как-то на Андроиде? Если да, то было бы отлично сделать это...

79
Java Timer. Отсчет времени после старта потока

Java Timer. Отсчет времени после старта потока

Я использую Timer и устанавливаю таймер через метод shedule(), задавая повтор каждые N секундНо столкнулся с проблемой, мне необходимо запускать...

81