PHP: несколько AJAX запросов с долговременной обработкой на сервере
Мне нужно получить данные с серверного скрипта, который обрабатывает и возвращает ответ, к примеру, через минуту. Если я посылаю, например, сразу два AJAX запроса, то ответ обоих я получу через две минуты (первый — через минуту, второй — через две). Как сделать так, чтоб один клиент мог своими действиями создавать два независимых процесса (а не один процесс со стеком запросов) на сервере, чтоб данные начали обрабатываться сразу, а ответ пришел через минуту, а не через две?
|
почитай про pcntl_fork() в PHP
|
Если я правильно понял pcntl_fork распараллеливает работу на сервере. Т. е. клиент послал один запрос, сервер создал несколько потоков... А я посылаю много запросов, эти запросы всё равно будут храниться в стеке.
|
Цитата:
Делаете запрос на сервер, сервер создает дополнительный поток. А из основного выходит, тоесть отпускает клиента. Клиент же в свою очеред через пару минут снова обращается к серверу для получения информации о завершении обработки данных в потоке, если порожденный поток выполнил свою работу, он к примеру на сервере устанавливает некий триггер в сессии/БД это уж вам решать как сохранить, клиент обращается к серверу и проверив триггер понимает завершен поток или нет, если да то получает уже данные обработанные из сессии/БД. |
примерно так:
<?php // Создаем сессию $expireTime = 60*60*24*30; session_set_cookie_params( $expireTime ); session_start(); // Подготавливаем массив процессов if ( !isset( $_SESSION['forks'] ) ) { $_SESSION['forks'] = array(); } if ( isset( $_GET['action'] ) ) { switch( $_GET['action'] ) { case "startProcess": // генерим уникальный ключ для процесса $processId = md5( mktime() ); // ставим процессу статус не завершен $_SESSION['forks'][ $processId ] = false; // создаем процесс $pid = pcntl_fork(); // С этого участка кода сразу же начнет работать дочерний поток if ( $pid == -1 ) { // Если поток создать не удалось // Уничтожаем инфу о процессе unset( $_SESSION['forks'][ $processId ] ); exit( "Create process failed" ); } else if ( $pid ) { // Сюда попадет родительский поток, тоесть основной exit( "Process started. Current process PID: ".$processId ); } else { // сюда попадет дочерний/порожденный поток // ......... обрабатываем данные // ставим статус завершен $_SESSION['forks'][ $processId ] = true; // завершаем процесс exit(); } break; case "processStatus": // Если передали ID процесса и он есть в массиве процессов if ( isset( $_GET['pid'] ) && isset( $_SESSION['forks'][ $_GET['pid'] ] ) ) { // Проверяем статус if ( $_SESSION['forks'][ $_GET['pid'] ] ) { // Уничтожаем инфу о процессе unset( $_SESSION['forks'][ $processId ] ); $status = "complete"; } else { $status = "working"; } exit( "Process status ".$status ); } exit( "Process not found" ); break; default; } } ?> |
запускать это дело примерно так:
Стартануть процесс: http://somesite.com/fork.php?action=startProcess Проверить статус: http://somesite.com/fork.php?action=processStatus&pid={PROCESSID} |
Цитата:
|
кстати, интересно, что опера выполняет один запрос, если в двух вкладках попытаться открыть один и тот же url :)
|
Ребята тупо удалили сессию, запросы стали обрабатываться параллельно :D
|
потому что на открытый файл сессии ставится блокировка, нельзя из двух процессов получить доступ к сессии. Т.е. либо не использовать в этом месте сессию, либо закрывать побыстрее.
|
Часовой пояс GMT +3, время: 00:39. |