PDA

Просмотр полной версии : Многопоточность на PHP


Shaitan-Devil
30.12.2008, 12:29
Введение
Решил написать о многопоточности в PHP. Иногда бывает,что работа выполняется быстрее в нескольких потоках. Полноценную многопоточность как в Perl в PHP можно организовать с натяжкой. Но все же существует несколько способов
1)Запуск нескольких копий скрипта с помощью функции system

system("/usr/local/bin/php -f index.php par1 par2&");

Но этот вариант не практичный. Т.к. Нужен сервер с огромным каналом и огромным количеством Оперативной Памяти.
2)PHP Thread
Чесnно говоря метод для меня новый.НО как оказалаось весьма полезный.
master.php

<?php
$array = array( /*Создаем массив*/
0 => 'thread',
1 => 'hello',
2 => 'world');
thread_set('mySharedVar', $array);/*Расшариваем его для thread.php*/
thread_include('thread.php');/*Инклдуим thread.php*/
sleep(3);/*Ждем 3 секунды пока выполняется*/
echo 'Done';/*Выводим Done*/
?>

thread.php

<?php
$array = thread_get('mySharedVar');
print_r($array);
sleep(5);
echo 'Done';
?>

Честно стибрено Отсюда (http://github.com/danhen/php_threads/tree/master)
3)Использование функции pcntl для организации (распараллеливания) процессов.
Основная функция

int pcntl_fork ( void )

Функция для создания дочерних процессов от основного.
Пример с мануала по PHP.

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

?>

Фунция pcntl_alarm(тайм аут). Дает сигнал следующему процессу через указанное количество секунд
Пример с мануала по PHP.

<?php
*** declare(ticks = 1);

*** function signal_handler($signal) {
** * ** print "Caught SIGALRM\n";
** * ** pcntl_alarm(5);
*** }

*** pcntl_signal(SIGALRM, "signal_handler", true);
*** pcntl_alarm(5);

*** for(;;) {
*** }

?>

pcntl_exec() Запуск еще одной программы одновременно с использованием скрипта. Можно юзать для запуска копии скрипта. Альтернатива 1 варианту

pcntl_exec("/usr/local/bin/php -f thread.php");

Скомбинировав эти фунции можно сделать многпоточность. Кстати, pcntl -это модуль, и его в стандартной сборке PHP нет.
Многпоточность в контексте сетевого взаимодействия
4)С помощью cURL(curl_multi)

$mh=curl_multi_init();//Открываем сессию curl_multi
// выполняем запрос
$running = null;
* do {
* * curl_multi_exec($mh, $running);
* } while($running> 0);
*
* // получаем данные и уничтожаем дискриптор
* foreach($curly as $id => $c) {
* * $result[$id] = curl_multi_getcontent($c);
* * curl_multi_remove_handle($mh, $c);
* }
*
* // закрываем многосложный дескриптор
* curl_multi_close($mh);

5)Неблокируемые сокеты
Можно использовать уже готовые классы с неблокируемыми сокетами,вы их без труда найдете если погуглите)
Либо

while(true)
{
//Код
if(max_threads=count($sock))
{
//Код
}
//Создаем сокет
$errno = 0;
$error = “”;

$socket = fsockopen($url_info[host], $url_info[port], $errno, $error, 30);
stream_set_blocking($socket, 0);
stream_set_timeout($socket, 3600);
fputs($socket, $query);

// запоминаем запущенный сокет

$sockets[md5(time())] = $socket;


Заключение
Ну вот в приницпе и все. Знаю,что написал бред,подкорректируйте плз.
Материал по теме
_http://habrahabr.ru/blogs/php/40545/ - Еще одна реализация многопоточности на PHP
_http://habrahabr.ru/blogs/php/40245/ - Эмуляция многопоточности в PHP
_http://habrahabr.ru/blogs/php/40432/ - Многопроцессовые демоны на PHP

Qwazar
30.12.2008, 12:46
Shaitan-Devil, имхо для статьи недостаточно подробно + для pcntl_fork не написаны методы прострелить себе ногу. Т.е. то на чём обязательно проколятся новички, при попытке её использования на практике.

groundhog
30.12.2008, 13:14
Наверное, создатели CURL в гробу перевернулись, когда их детище поставили в один ряд с функциями pcntl_*. Как это можно сравнивать? Да, это многопоточность, но в контексте сетевого взаимодействия... В общем было миллиард статей на эту тему, это одна из худших...

От себя дополню:

http://github.com/danhen/php_threads/tree/master

[Raz0r]
30.12.2008, 15:21
На античате традиция - раз в год кто-нибудь пишет про многопоточность в php =)
По сабжу: в примере "Запуск нескольких копий скрипта с помощью функции system" нет даже символа &, обозначающего переход выполнения команды в бэкграунд, т.е. без ожидания ее завершения. В твоем примере этого нет.

"Использование функции pcntl для организации (распараллеливания) процессов."
Спасибо мануал мы тоже умеем читать. Хотя бы свои наработки показал бы.

"С помощью cURL(curl_multi)"
среди всех перечисленных способов этот наименее всего подходит под понятие организации многопоточности. К этой же серии также относятся неблокирующие сокеты, о которых вообще ничего не сказано в твоей статье.
И как упомянул groundhog ничего нет про php_threads
В общем слабо.
p.s. выйдет PHP6 тогда и поговорим о многопоточности

Qwazar
30.12.2008, 16:18
Запускайте 20 копий скрипта ... вот вам и многопоточность) Угу, а синхронизация при помощи бд :)))

Shaitan-Devil
30.12.2008, 16:20
Спасибо за конструктивную критику, будем фиксить баги.

gibson
30.12.2008, 18:21
функции pcntl
забыл дописать, что под виндой не работает.

http://php.su/functions/?cat=pcntl

все остальное от лукавого.

KaZ@NoVa
30.12.2008, 19:39
скрипты на php не могут использовать многопоточность
Единственное, что можно сделать это запустить один и тот же скрипт несколько раз, с разными параметрами, чтобы каждый запущенный скрипт обрабатывал свою часть данных.

KaZ@NoVa
30.12.2008, 19:55
дааа,пхп конечно не перл=\,многопоточности как такой и нету,ее можно симулировать с помощью неблокирующихся сокетов и библиотек,типа мультикурл


изучил довольно много информации по данной теме и пришел к выводу,нужно реализовывать на неблокируемых сокетах (мультикурл мне не понравился тем, что он может обрабатывать только пачками, т.е. при обработке 100 урлов на конечном этапе имеем снижение производительности - допустим 98 уже обработалось и вся система ждет обработку каких то 2х тормозных урлов, в конечном итоге теряя время).

Плотно пошарив в инете нашёл таки класс AunoAsyncHttp, на котором в дальнейшем я и выстраивал все свои многопоточные скрипты.

Shaitan-Devil
30.12.2008, 20:46
Пофиксил некоторые баги.

Shadow_p1raT
31.12.2008, 15:00
Материал по теме
_http://habrahabr.ru/blogs/php/40545/ - Еще одна реализация многопоточности на PHP
_http://habrahabr.ru/blogs/php/40245/ - Эмуляция многопоточности в PHP
_http://habrahabr.ru/blogs/php/40432/ - Многопроцессовые демоны на PHP

zerling
12.02.2009, 07:44
экспериментировал с этой темой, запускал дочерние скрипты с кодом типа sleep(100) , дак вот - функция system() будет дожидаться выполнения дочернего скрипта даже если поставить амперсанд, поэтому она не подходит! Для этого надо использовать popen() , она не ждет завершения процесса

Nakq
24.02.2009, 18:39
не получается(

zerling
26.02.2009, 15:47
не получается(
короче да, почему то на многих серверах эта ф-ция не работает

-Hormold-
26.02.2009, 18:06
Может и боян, но всё-таки понравилось :(