Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   PHP: несколько AJAX запросов с долговременной обработкой на сервере (https://javascript.ru/forum/server/25773-php-neskolko-ajax-zaprosov-s-dolgovremennojj-obrabotkojj-na-servere.html)

FINoM 15.02.2012 06:48

PHP: несколько AJAX запросов с долговременной обработкой на сервере
 
Мне нужно получить данные с серверного скрипта, который обрабатывает и возвращает ответ, к примеру, через минуту. Если я посылаю, например, сразу два AJAX запроса, то ответ обоих я получу через две минуты (первый — через минуту, второй — через две). Как сделать так, чтоб один клиент мог своими действиями создавать два независимых процесса (а не один процесс со стеком запросов) на сервере, чтоб данные начали обрабатываться сразу, а ответ пришел через минуту, а не через две?

devote 15.02.2012 07:13

почитай про pcntl_fork() в PHP

FINoM 17.02.2012 03:27

Если я правильно понял pcntl_fork распараллеливает работу на сервере. Т. е. клиент послал один запрос, сервер создал несколько потоков... А я посылаю много запросов, эти запросы всё равно будут храниться в стеке.

devote 17.02.2012 12:19

Цитата:

Сообщение от FINoM
Т. е. клиент послал один запрос, сервер создал несколько потоков...

Не совсем правильно, я так понял вы хотите разгрузить клиента от ожидаемых запросов. Для этого и есть fork. Тоесть все просто.
Делаете запрос на сервер, сервер создает дополнительный поток. А из основного выходит, тоесть отпускает клиента. Клиент же в свою очеред через пару минут снова обращается к серверу для получения информации о завершении обработки данных в потоке, если порожденный поток выполнил свою работу, он к примеру на сервере устанавливает некий триггер в сессии/БД это уж вам решать как сохранить, клиент обращается к серверу и проверив триггер понимает завершен поток или нет, если да то получает уже данные обработанные из сессии/БД.

devote 17.02.2012 13:02

примерно так:

<?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;
		}
	}
?>

devote 17.02.2012 13:07

запускать это дело примерно так:
Стартануть процесс:
http://somesite.com/fork.php?action=startProcess

Проверить статус:
http://somesite.com/fork.php?action=processStatus&pid={PROCESSID}

x-yuri 20.02.2012 13:48

Цитата:

Сообщение от FINoM
Как сделать так, чтоб один клиент мог своими действиями создавать два независимых процесса (а не один процесс со стеком запросов) на сервере,

[telepath mode]вызывать session_write_close как можно быстрее или не запускать 2 одинаковых запроса в ff/chrome[/telepath mode]

x-yuri 20.02.2012 14:48

кстати, интересно, что опера выполняет один запрос, если в двух вкладках попытаться открыть один и тот же url :)

FINoM 18.03.2012 01:19

Ребята тупо удалили сессию, запросы стали обрабатываться параллельно :D

x-yuri 20.03.2012 19:50

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


Часовой пояс GMT +3, время: 05:27.