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

158
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Есть два слушателя для каждого свой:

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

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

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

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

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

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

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

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

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

131