Master-X
Регистрация
|
Вход
Форум
|
Новости
|
Статьи
Главная
»
Форум
»
Программинг, Скрипты, Софт, Сервисы
»
Тема:
PHP многопоточность
Новая тема
Ответить
цитата
29/03/11 в 11:34
FXIX
Гуру подскажите как реализовать нормальную многопоточность на пхп. Вот как я вижу:
http://pastebin.com/LdSTxDNZ
Т.е. в кроне раз в 5 минут запускается файл run_10_proccess.php, который в 10 потоков запускает файл index.php. Если схема правильна то вопросы:
- если 10 потоков скрипта не укладываются в 5 минут то что будет? просто другой экземпляр run_10_proccess.php запуститься и ничего страшного не произойдет. так?
- как быть с логами самого скрипта который пускаем? в обычном виде в кроне такое:
*/5 * * * * php /scripts/index.php >> /logs/index.log
т.е. все сыпется в index.log. Для верхнего случая логи исполняемого скрипта будут сыпаться в лог run_10_proccess.log?
p.s. тема не касается ни курлов ни мультикурлов ни сокетов ни парсеров. Решение в общем виде.
цитата
29/03/11 в 13:04
Stek
каждый поток создает файл времянку, по окончанию его удаляет. Если перед запуском файл есть - значит процесс уже работает. Ну или чуть сложнее, на наличие себя в процессах проверять.
цитата
29/03/11 в 13:08
Pentarh
Насчет многопоточности - нужно расширение pcntl. Правда оно как то смещает стандартные коды возврата сабшеллов и всякие там exec(),system(),mail() функции начнут возвращать другие результаты.
http://code.google.com/query/#q=pcntl_fork
А насчет повторного запуска
Предотвращение двойного запуска cron задач
цитата
29/03/11 в 14:42
dDan
Вижу себе решение в изучение питона. В свое время тоже убил немало времени на пхп и многопточность и ничего лучше чем pcntl и задач во временых таблицах мускула не нашел. Но и это считай извратом. Питон прост и удобен
цитата
29/03/11 в 15:12
Pentarh
Да Perl как бэ тоже ничо
Не пиздите на многопоточность похапэ! Может она и через жопу реализована, но
есть же в природе веб сервера на похапэ
писаные.
цитата
29/03/11 в 16:46
mr. snatch
pcntl_* тоже как бы ниразу не многопоточность, зато, позволяет нормально сигналами между своих процессов обмениваться.
кстати, использование flock-ов в качестве мъютексов, тоже не всегда прокатывает, ещё боле-менее, если файлы использовать просто в качестве флагов, но вот что бы обмениваться инфой между процессами и синхронизировать их таким способом, лучше всего использовать, как не банально, - мускул с эксключивным локом таблиц (lock tables) и вот уже таким обрахом писать/читать как состояния процессов, так и обмениваться информацией.
В общем, в пыхе нет нейтивных потоков (есть всякие патчи, но как бы хз насчёт ихнего будущего и вообще не слежу за всем, что допиливается кем-то на стороне, и может отсутствовать на обычном шареде) и их эмуляция - дело мутное и зависит от особенностей поставленной задачи (где просто узнать о существовании запущенного процесса, ну а где и полноценное interprocess communication понадобится), и посему моё имхо - юзать питон (ну или пёрл) в таких случаях
цитата
29/03/11 в 21:07
JM
все гараздо проще...
делаешь .sh пакет где у тебя
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
и его в крон с какой переодичностью сам решай...
первой строчкой делаешь mysql "select count from temportytable limit 1;"
потом
if ($count>10)
{
exit;
}
else
{
запросик "update temportytable set count=count+1;"
}
в конце скрипта
запросик "update temportytable set count=count-1;"
как только у тебя по крону запуститься 10 процессов (рабочих) скрипт будет тупо убиваться в начале
я лично смотрю еще la и %idle из top и по этим параметрам тоже запускаю или не запускаю скрипт получаю любое количество потоков и нагрузку ;)
цитата
30/03/11 в 10:50
AWD
имхо, мускуль - не решение.
например, скрипт вылетит, не отметится в мускуле - и привет! будет считаться запущенным...
лучше лочить файлы flock($file, 2);
после отработки либо вылета скрипта файл анлочится автоматом. каждому потоку дать номер, правильно выставить set_time_limit - и вперед.
файл - пускач: main.php
Код:
$thread_dir = "threads/"; $max_threads = 10;
for($i=0; $i<$max_threads; $i++)
if(($tmp_file = fopen($thread_dir.$i, "w")))
if(flock($tmp_file, 2) == false) {
fclose($tmp_file);
echo 'Поток '.$i." уже работает\r\n";
continue;
}
else {
fclose($tmp_file);
//запускаем поток (я делал через хттп)
$fp = fsockopen('www.myhost.com', 80, $errno, $errstr, 1);
fputs($fp, "GET /do.php?thread=".$i." HTTP/1.0\r\nHost:
myhost.com\r\n\r\n");
usleep(500);
fclose($fp);
}
ну а в do.php
Код:
ignore_user_abort(true);
set_time_limit(600); //0 не пойдет, а вдруг зависнет..
$thread = $_GET['thread'];
$in_work = fopen($thread_dir.$thread, "w");
flock($in_work, 2);
//тут делаем дело
flock($in_work, 3);
как-то так.
main.php пускай хоть каждую минуту, он запустит только не работающие потоки.
цитата
30/03/11 в 11:00
Pentarh
mr. snatch писал:
pcntl_* тоже как бы ниразу не многопоточность, зато, позволяет нормально сигналами между своих процессов обмениваться.
Да ладно
? Или ты имеешь в виду треды? А ассемблерных вставок не хотел? )) Это ж пхп епт.
mr. snatch писал:
лучше всего использовать, как не банально, - мускул с эксключивным локом таблиц (lock tables) и вот уже таким обрахом писать/читать как состояния процессов, так и обмениваться информацией.
OMFG ) Слушай, ну ведь нормальный префорковый вебсервер Nanoweb. И никакого мускуля там нет.
JM писал:
все гараздо проще...
делаешь .sh пакет где у тебя
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
/usr/bin/php index.php
Бля, ну ацкие кодеры чисто собрались )) Эта шняга запустит
последовательно
10 процессов. Один за другим. Охуенная многопоточность. Тогда уж так:
Код:
#!/bin/bash
for i in `seq 10` ; do
/usr/bin/php index.php >/dev/null 2>&1 &
done
echo "10 processes started"
цитата
30/03/11 в 13:13
mr. snatch
нановеб - не тот случай. Я говорю о решении, которое может работать на основной массе хостингов, и вот ПЫХ такими фитчами просто не располагает, и вот когда тебе нужно будет обмениваться определённой структурированной информацией между инстансами (которые могут и имеют полное право одновременно писать или читать какую-то свою часть), то просто flock-ов будет недостаточно, и гарантированный эксклюзивный lock достигается только блокировкой таблиц.
Причём здесь ассемблер вообще, я говорю всего-лишь об
pthreads
то есть многопоточности, а не форках, споувнах и прочей немногопоточности.
цитата
30/03/11 в 15:30
FXIX
спасибо господа всех заценил. наверно на локе файла остановлюсь
цитата
30/03/11 в 15:34
Pentarh
mr. snatch писал:
Причём здесь ассемблер вообще, я говорю всего-лишь об
pthreads
то есть многопоточности, а не форках, споувнах и прочей немногопоточности.
Вот ты деревянный. Какие pthreads ты хотел от
P
ersonal
H
ome
P
age (ну или hypertext preprocessor - кому как нравится)?
цитата
30/03/11 в 16:39
mr. snatch
Есть такое понятие - многопоточность, так же сущетсвует и то, что ты называешь многопоточностью эмулируя на ПЫХе. Вот то, про что говоришь ты - это форк, и с многопоточностью он ничего общего не имеет.
Да, есть различные эмуляции сабжа, но по каким таким признакам ты соотносишь мою деревянность и отсутствие сабжа в php, для меня загадка, я просто говорю о том, что если нужна действительно многопоточность, имеет смысл пересмотреть язык разработки.
выбирай выражения в общем )
цитата
30/03/11 в 17:24
FXIX
граждане просветленные кодеры, только не ругайтесь. итак вас мало
цитата
01/04/11 в 22:30
FXIX
вообщем написал хренатень такую. кстати опрашивать файл на заблокированность не надо. когда первый разлочит так сразу второй его залочит, итд. и файл открываем как 'a' а не как 'w'. w очищает файл. по сути пересоздает. наткнулся на обсуждение что типа где-то когда-то на каких-то платформах лок из-за этого могет не сработать
# Блокировка файла
class LockFile {
public function __construct() {
$this->file = fopen('1.lock', "a"); # открываем файл на запись
}
public function lock() {
flock($this->file, LOCK_EX); # блокируем файл на запись
echo 'момент лока: '. date('H:i:s');
}
public function unlock() {
flock($this->file, LOCK_UN); # разблокировка файла
echo 'момент разлока: '. date('H:i:s');
}
public function __destruct() {
fclose($this->file);
}
}
# Использование
$lockfile=new LockFile();
$lockfile->lock();
echo 'код';
$lockfile->unlock();
unset($lockfile);
цитата
02/04/11 в 15:30
Heavy
FXIX писал:
наткнулся на обсуждение что типа где-то когда-то на каких-то платформах лок из-за этого могет не сработать
Да уже тут тоже перетирали про flock у пыха, например -
PHP и mutex
. Сами пыходелы в документации по flock тоже об этом возможном обломе предупреждают. Мне же как-то очень везет на системы с такими рпоблемами, почти каждая не блокирует как следует. А всего-то стоило внести в "язык" мьютексы и семафоры какие-либо.
цитата
05/04/11 в 15:09
EllGree
Писал многопоточные системы на php, все работало отлично.
По крону запускается загрузчик, который проверяет "ps | grep" есть ли управляющий процесс, если нет, запускает, есть - отваливает (опционально: если время выполнения управляющего процесса больше, чем заданное значение - kill & перезапуск).
Управляющий процесс в бесконечном цикле проверяет "ps | grep" сколько рабочих процессов трудятся, если меньше заданного значения, подбрасывают дровишек, а также проверяет флаги ресурсов (дату создания файла, имя которого - занятый ресурс, содержание - PID рабочего процесса) - если файл создан ранее чем time()-заданное значение максимального времени работы процесса, процесс прибивается, файл удаляется, в общий лог заносится замечание о таймауте.
Ну и скрипт для веб-мониторинга того, что происходит в системе, анализ лога ошибок, прибивание процессов руками, настройка констант таймаутов и кол-ва процессов.
цитата
05/04/11 в 16:36
alex.raven
В своё время я потратил много времени на решение проблемы многопоточности в PHP. Создавать временные файлы или флаги в базе это ненадёжно, т.к скрипт может аварийно завершиться (например, исчерпает память) и не удалит временный файл. Ну и конечно же, перестанет запускаться.
В конце-концов, я пришёл к решению, которое у меня успешно работает в нескольких проектах. Здесь используется три скрипта - два шелл и один пхп. Первый шелл скрипт запускается из крона и служит для запуска всех тредов. Второй следит за тем, чтобы каждого треда было запущено не больше одного (причём он не "сломается", если предыдущий тред завершился аварийно). Ну и собственно, сам PHP скрипт, который делает нужную нам работу. Он получает в качестве параметра номер своего треда (в примере - от 1 до 10). Для каждого треда ведётся отдельный лог, куда записывается весь вывод PHP скрипта.
start_threads.sh (главный скрипт, который запускается каждую минуту в кроне):
Код:
#!/bin/bash
# задаём путь, где у нас лежат скрипты, т.к этот скрипт запускается по крону
DIR=/path/to/your/scripts
cd $DIR
# кол-во одновременно запущенных тредов
max=10
count=1
while [ $count -le $max ]
do
$DIR/thread.sh $count &
count=$(( $count + 1 ))
done
thread.sh (он следит за тем, чтобы пхп треды не запускались больше одного раза):
Код:
#!/bin/sh
DIR=/path/to/your/scripts
myname=`basename $0`
if test -r $DIR/$myname_$1.pid; then
RPID=$(cat $DIR/$myname_$1.pid)
if $(kill -CHLD $RPID >/dev/null 2>&1)
then
exit 0
fi
fi
# store my pid
echo $$ > $DIR/$myname_$1.pid
PHP=/usr/bin/php
cd $DIR
# запускаем PHP тред и передаём ему в качестве параметра номер его треда, вывод записываем в лог
$PHP $DIR/thread.php $1 >> $DIR/thread_$1.log
ну и собственно сам PHP скрипт (в данном примере ничего не делает, кроме как выводит "Тред такой-то запущен", что попадает в лог).
Код:
<?php
// получаем номер треда
$thread = $argv[1];
// выводим тестовое сообщение, не забыв \n в конце, а то наш лог будет весь в одну строчку ;)
echo "Тред {$thread} запущен\n";
?>
цитата
05/04/11 в 21:56
JM
Pentarh писал:
Бля, ну ацкие кодеры чисто собрались )) Эта шняга запустит
последовательно
10 процессов. Один за другим. Охуенная многопоточность. Тогда уж так:
Код:
#!/bin/bash
for i in `seq 10` ; do
/usr/bin/php index.php >/dev/null 2>&1 &
done
echo "10 processes started"
Пост до конца перечитай...
цитата
05/04/11 в 22:00
JM
Походу тут никто не в курил в саму суть задача, а для чего вам ОДНОВРЕМЕННО 10 потоков? Что бы ждать пока они на 4х или 2х ядернике по сути поочереди отработаються?
цитата
05/04/11 в 23:17
Dr.Syshalt
JM:
Тоже начал читать топик (давно не заходил) и не понял - обычно люди стараются, чтобы задачи крона не запускались пачками, а напротив, как можно меньше грузили сервер. И как раз запускать их для этого лучше последовательно.
цитата
05/04/11 в 23:24
EllGree
JM писал:
Походу тут никто не в курил в саму суть задача, а для чего вам ОДНОВРЕМЕННО 10 потоков? Что бы ждать пока они на 4х или 2х ядернике по сути поочереди отработаються?
Ну, например, собрать статсы с тысячи спонсоров, многие из которых могут отдавать их по 2-5 минут. Если собирать их последовательно, то можно легко в сутки не уложиться.
цитата
05/04/11 в 23:43
Dr.Syshalt
EllGree писал:
Ну, например, собрать статсы с тысячи спонсоров, многие из которых могут отдавать их по 2-5 минут. Если собирать их последовательно, то можно легко в сутки не уложиться.
Ну тогда не мильоны скриптов надо запускать параллельно, а один грамотно написать и запустить.
http://www.ibuildings.co.uk/blog/archives/811-Multithreading-in-PHP-with-CURL.html
как раз для таких задач подходит.
цитата
05/04/11 в 23:49
EllGree
Dr.Syshalt писал:
Ну тогда не мильоны скриптов надо запускать
Речь-то шла о десятке тредов.
curl_multi_* мне известен, как раз в приведенном мной примере такое решение не подходит, поскольку система писалась не с нуля на тыщу спонсоров, а по мере их добавления с фиг знает какого года.
цитата
06/04/11 в 12:25
AWD
FXIX писал:
кстати опрашивать файл на заблокированность не надо. когда первый разлочит так сразу второй его залочит, итд.
так речь шла о том, если файл залочен, то процесс запущен. зачем еще ожидающие процессы размножать?
alex.raven писал:
Создавать временные файлы или флаги в базе это ненадёжно, т.к скрипт может аварийно завершиться (например, исчерпает память) и не удалит временный файл. Ну и конечно же, перестанет запускаться.
почему перестанет? хуй на временный файл, что не удалили, лок снимется с файла вместе с процессом.
Стр.
1
,
2
>
последняя »
Новая тема
Ответить
Эта страница в полной версии