Реклама на сайте Advertise with us

PHP многопоточность

Расширенный поиск по форуму
 
Новая тема Новая тема   
Автор
Поиск в теме:

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 29/03/11 в 11:34       Ответить с цитатойцитата 

Гуру подскажите как реализовать нормальную многопоточность на пхп. Вот как я вижу: 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. тема не касается ни курлов ни мультикурлов ни сокетов ни парсеров. Решение в общем виде.

пришел к победе коммунистического труда

0
 

www.phpdevs.com

С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105


Передовик Master-X (01.09.2005) Передовик Master-X (16.09.2005) Передовик Master-X (01.10.2005) Передовик Master-X (16.08.2006) Передовик Master-X (16.10.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 29/03/11 в 13:04       Ответить с цитатойцитата 

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

Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.

5
 

Криптопохуист

С нами с 05.04.03
Сообщения: 17158
Рейтинг: 6019

Ссылка на сообщениеДобавлено: 29/03/11 в 13:08       Ответить с цитатойцитата 

Насчет многопоточности - нужно расширение pcntl. Правда оно как то смещает стандартные коды возврата сабшеллов и всякие там exec(),system(),mail() функции начнут возвращать другие результаты.

http://code.google.com/query/#q=pcntl_fork

А насчет повторного запуска

Предотвращение двойного запуска cron задач

5
 



С нами с 18.08.04
Сообщения: 6376
Рейтинг: 4430

Ссылка на сообщениеДобавлено: 29/03/11 в 14:42       Ответить с цитатойцитата 

Вижу себе решение в изучение питона. В свое время тоже убил немало времени на пхп и многопточность и ничего лучше чем pcntl и задач во временых таблицах мускула не нашел. Но и это считай извратом. Питон прост и удобен

5
 

Криптопохуист

С нами с 05.04.03
Сообщения: 17158
Рейтинг: 6019

Ссылка на сообщениеДобавлено: 29/03/11 в 15:12       Ответить с цитатойцитата 

Да Perl как бэ тоже ничо

Не пиздите на многопоточность похапэ! Может она и через жопу реализована, но есть же в природе веб сервера на похапэ писаные.

5
 



С нами с 24.06.10
Сообщения: 2686
Рейтинг: 543

Ссылка на сообщениеДобавлено: 29/03/11 в 16:46       Ответить с цитатойцитата 

pcntl_* тоже как бы ниразу не многопоточность, зато, позволяет нормально сигналами между своих процессов обмениваться.
кстати, использование flock-ов в качестве мъютексов, тоже не всегда прокатывает, ещё боле-менее, если файлы использовать просто в качестве флагов, но вот что бы обмениваться инфой между процессами и синхронизировать их таким способом, лучше всего использовать, как не банально, - мускул с эксключивным локом таблиц (lock tables) и вот уже таким обрахом писать/читать как состояния процессов, так и обмениваться информацией.

В общем, в пыхе нет нейтивных потоков (есть всякие патчи, но как бы хз насчёт ихнего будущего и вообще не слежу за всем, что допиливается кем-то на стороне, и может отсутствовать на обычном шареде) и их эмуляция - дело мутное и зависит от особенностей поставленной задачи (где просто узнать о существовании запущенного процесса, ну а где и полноценное interprocess communication понадобится), и посему моё имхо - юзать питон (ну или пёрл) в таких случаях

removed by moderator

5
 



С нами с 08.02.03
Сообщения: 10564
Рейтинг: 5962


Передовик Master-X (01.06.2018) Передовик Master-X (16.06.2019) Передовик Master-X (01.04.2020) Передовик Master-X (16.04.2020) Передовик Master-X (16.10.2021) Ветеран трепа Master-X (01.11.2021)
Ссылка на сообщениеДобавлено: 29/03/11 в 21:07       Ответить с цитатойцитата 

все гараздо проще...
делаешь .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 и по этим параметрам тоже запускаю или не запускаю скрипт получаю любое количество потоков и нагрузку ;)

5
 



С нами с 03.02.11
Сообщения: 842
Рейтинг: 301

Ссылка на сообщениеДобавлено: 30/03/11 в 10:50       Ответить с цитатойцитата 

имхо, мускуль - не решение.
например, скрипт вылетит, не отметится в мускуле - и привет! будет считаться запущенным...
лучше лочить файлы 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 пускай хоть каждую минуту, он запустит только не работающие потоки.

5
 

Криптопохуист

С нами с 05.04.03
Сообщения: 17158
Рейтинг: 6019

Ссылка на сообщениеДобавлено: 30/03/11 в 11:00       Ответить с цитатойцитата 

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"

5
 



С нами с 24.06.10
Сообщения: 2686
Рейтинг: 543

Ссылка на сообщениеДобавлено: 30/03/11 в 13:13       Ответить с цитатойцитата 

нановеб - не тот случай. Я говорю о решении, которое может работать на основной массе хостингов, и вот ПЫХ такими фитчами просто не располагает, и вот когда тебе нужно будет обмениваться определённой структурированной информацией между инстансами (которые могут и имеют полное право одновременно писать или читать какую-то свою часть), то просто flock-ов будет недостаточно, и гарантированный эксклюзивный lock достигается только блокировкой таблиц.
Причём здесь ассемблер вообще, я говорю всего-лишь об pthreads то есть многопоточности, а не форках, споувнах и прочей немногопоточности.

removed by moderator

5
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 30/03/11 в 15:30       Ответить с цитатойцитата 

спасибо господа всех заценил. наверно на локе файла остановлюсь

пришел к победе коммунистического труда

0
 

Криптопохуист

С нами с 05.04.03
Сообщения: 17158
Рейтинг: 6019

Ссылка на сообщениеДобавлено: 30/03/11 в 15:34       Ответить с цитатойцитата 

mr. snatch писал:
Причём здесь ассемблер вообще, я говорю всего-лишь об pthreads то есть многопоточности, а не форках, споувнах и прочей немногопоточности.

Вот ты деревянный. Какие pthreads ты хотел от Personal Home Page (ну или hypertext preprocessor - кому как нравится)?

5
 



С нами с 24.06.10
Сообщения: 2686
Рейтинг: 543

Ссылка на сообщениеДобавлено: 30/03/11 в 16:39       Ответить с цитатойцитата 

Есть такое понятие - многопоточность, так же сущетсвует и то, что ты называешь многопоточностью эмулируя на ПЫХе. Вот то, про что говоришь ты - это форк, и с многопоточностью он ничего общего не имеет.
Да, есть различные эмуляции сабжа, но по каким таким признакам ты соотносишь мою деревянность и отсутствие сабжа в php, для меня загадка, я просто говорю о том, что если нужна действительно многопоточность, имеет смысл пересмотреть язык разработки.
выбирай выражения в общем )

removed by moderator

5
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 30/03/11 в 17:24       Ответить с цитатойцитата 

граждане просветленные кодеры, только не ругайтесь. итак вас мало smail101.gif

пришел к победе коммунистического труда

0
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 01/04/11 в 22:30       Ответить с цитатойцитата 

вообщем написал хренатень такую. кстати опрашивать файл на заблокированность не надо. когда первый разлочит так сразу второй его залочит, итд. и файл открываем как '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);

пришел к победе коммунистического труда

0
 



С нами с 01.03.06
Сообщения: 629
Рейтинг: 620

Ссылка на сообщениеДобавлено: 02/04/11 в 15:30       Ответить с цитатойцитата 

FXIX писал:
наткнулся на обсуждение что типа где-то когда-то на каких-то платформах лок из-за этого могет не сработать


Да уже тут тоже перетирали про flock у пыха, например - PHP и mutex . Сами пыходелы в документации по flock тоже об этом возможном обломе предупреждают. Мне же как-то очень везет на системы с такими рпоблемами, почти каждая не блокирует как следует. А всего-то стоило внести в "язык" мьютексы и семафоры какие-либо.

0
 



С нами с 19.07.05
Сообщения: 318
Рейтинг: 401

Ссылка на сообщениеДобавлено: 05/04/11 в 15:09       Ответить с цитатойцитата 

Писал многопоточные системы на php, все работало отлично.
По крону запускается загрузчик, который проверяет "ps | grep" есть ли управляющий процесс, если нет, запускает, есть - отваливает (опционально: если время выполнения управляющего процесса больше, чем заданное значение - kill & перезапуск).
Управляющий процесс в бесконечном цикле проверяет "ps | grep" сколько рабочих процессов трудятся, если меньше заданного значения, подбрасывают дровишек, а также проверяет флаги ресурсов (дату создания файла, имя которого - занятый ресурс, содержание - PID рабочего процесса) - если файл создан ранее чем time()-заданное значение максимального времени работы процесса, процесс прибивается, файл удаляется, в общий лог заносится замечание о таймауте.

Ну и скрипт для веб-мониторинга того, что происходит в системе, анализ лога ошибок, прибивание процессов руками, настройка констант таймаутов и кол-ва процессов.

0
 

Мотиватор :)

С нами с 06.05.09
Сообщения: 3028
Рейтинг: 607

Ссылка на сообщениеДобавлено: 05/04/11 в 16:36       Ответить с цитатойцитата 

В своё время я потратил много времени на решение проблемы многопоточности в 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";
?>

Just a signature.

0
 



С нами с 08.02.03
Сообщения: 10564
Рейтинг: 5962


Передовик Master-X (01.06.2018) Передовик Master-X (16.06.2019) Передовик Master-X (01.04.2020) Передовик Master-X (16.04.2020) Передовик Master-X (16.10.2021) Ветеран трепа Master-X (01.11.2021)
Ссылка на сообщениеДобавлено: 05/04/11 в 21:56       Ответить с цитатойцитата 

Pentarh писал:

Бля, ну ацкие кодеры чисто собрались )) Эта шняга запустит последовательно 10 процессов. Один за другим. Охуенная многопоточность. Тогда уж так:

Код:

#!/bin/bash
for i in `seq 10` ; do
   /usr/bin/php index.php >/dev/null 2>&1 &
done

echo "10 processes started"


Пост до конца перечитай...

0
 



С нами с 08.02.03
Сообщения: 10564
Рейтинг: 5962


Передовик Master-X (01.06.2018) Передовик Master-X (16.06.2019) Передовик Master-X (01.04.2020) Передовик Master-X (16.04.2020) Передовик Master-X (16.10.2021) Ветеран трепа Master-X (01.11.2021)
Ссылка на сообщениеДобавлено: 05/04/11 в 22:00       Ответить с цитатойцитата 

Походу тут никто не в курил в саму суть задача, а для чего вам ОДНОВРЕМЕННО 10 потоков? Что бы ждать пока они на 4х или 2х ядернике по сути поочереди отработаються?

0
 

Чингачгук, вождь красноглазых

С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824

Ссылка на сообщениеДобавлено: 05/04/11 в 23:17       Ответить с цитатойцитата 

JM: Тоже начал читать топик (давно не заходил) и не понял - обычно люди стараются, чтобы задачи крона не запускались пачками, а напротив, как можно меньше грузили сервер. И как раз запускать их для этого лучше последовательно.

0
 



С нами с 19.07.05
Сообщения: 318
Рейтинг: 401

Ссылка на сообщениеДобавлено: 05/04/11 в 23:24       Ответить с цитатойцитата 

JM писал:
Походу тут никто не в курил в саму суть задача, а для чего вам ОДНОВРЕМЕННО 10 потоков? Что бы ждать пока они на 4х или 2х ядернике по сути поочереди отработаються?

Ну, например, собрать статсы с тысячи спонсоров, многие из которых могут отдавать их по 2-5 минут. Если собирать их последовательно, то можно легко в сутки не уложиться.

0
 

Чингачгук, вождь красноглазых

С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824

Ссылка на сообщениеДобавлено: 05/04/11 в 23:43       Ответить с цитатойцитата 

EllGree писал:
Ну, например, собрать статсы с тысячи спонсоров, многие из которых могут отдавать их по 2-5 минут. Если собирать их последовательно, то можно легко в сутки не уложиться.


Ну тогда не мильоны скриптов надо запускать параллельно, а один грамотно написать и запустить.

http://www.ibuildings.co.uk/blog/archives/811-Multithreading-in-PHP-with-CURL.html

как раз для таких задач подходит.

0
 



С нами с 19.07.05
Сообщения: 318
Рейтинг: 401

Ссылка на сообщениеДобавлено: 05/04/11 в 23:49       Ответить с цитатойцитата 

Dr.Syshalt писал:
Ну тогда не мильоны скриптов надо запускать

Речь-то шла о десятке тредов.
curl_multi_* мне известен, как раз в приведенном мной примере такое решение не подходит, поскольку система писалась не с нуля на тыщу спонсоров, а по мере их добавления с фиг знает какого года.

0
 



С нами с 03.02.11
Сообщения: 842
Рейтинг: 301

Ссылка на сообщениеДобавлено: 06/04/11 в 12:25       Ответить с цитатойцитата 

FXIX писал:
кстати опрашивать файл на заблокированность не надо. когда первый разлочит так сразу второй его залочит, итд.
так речь шла о том, если файл залочен, то процесс запущен. зачем еще ожидающие процессы размножать? icon_confused.gif
alex.raven писал:
Создавать временные файлы или флаги в базе это ненадёжно, т.к скрипт может аварийно завершиться (например, исчерпает память) и не удалит временный файл. Ну и конечно же, перестанет запускаться.
почему перестанет? хуй на временный файл, что не удалили, лок снимется с файла вместе с процессом.

-1
 
Новая тема Новая тема   

Текстовая реклама в форме ответа
Заголовок и до четырех строчек текста
Длина текста до 350 символов
Купить рекламу в этом месте!


Перейти:  



Спонсор раздела Стань спонсором этого раздела!

Реклама на сайте Advertise with us

Опросы

Рецепт новогоднего блюда 2022



Обсудите на форуме обсудить (11)
все опросы »