PHP

индекс
206,80

Многопроцессовые демоны на PHP

Зачем может понадобиться писать демоны на PHP?
  • Выполнение трудоемких фоновых задач;
  • выполнение задач, которые длятся больше, чем время ожидания при HTTP-запросе (30 секунд);
  • выполнение задач на более высоком уровне доступа, чем серверный процесс (читай — под рутом).


Основы


  • PID — идентификатор процесса. Уникальное для текущего момента положительное число.
  • pcntl — расширение PHP для работы с дочерними процессами. Курим мануал.
  • posix — расширение PHP для работы с функциями стандарта POSIX. Курим мануал.


Если у тебя возникнет вопрос по поводу какой-то незнакомой функции — не расстраивайся! Они все задокументированы в PHP Manual. Вряд ли у меня получится рассказать о них подробнее и интереснее.

Форкинг (плодим процессы)


Как из одного процесса сделать два? Программистам под Windows (в том числе и мне) больше знакома система, когда мы пишем функцию, которая будет main() для дочернего потока. В *nix все не так, потому я немного расскажу об этой системе многопроцессовости. *nixоиды могут смело пропустить эту часть, если они и так все знают.

Итак. Есть такая функия pcntl_fork. Как ни странно, аргументов она не берет. Что же делать?

После pcntl_fork у скрипта начинается шизофрения: код вроде бы один и тот же, но выполняется двумя параллельными процессами. Впрочем, если просто вставить в скрипт pcntl_fork, ничего наглядного ты не увидишь, разве что конфликты доступа к ресурсам.

Фишка в том, что pcntl_fork возвращает 0 дочернему процессу и PID дочернего процесса — родительскому. Вот обычный паттерн использования pcntl_fork:

$pid = pcntl_fork();
if ($pid == -1) {
    //ошибка
} elseif ($pid) {
    //сюда попадет родительский процесс
} else {
    //а сюда - дочерний процесс
}            
//а сюда попадут оба процесса


Кстати, pcntl_fork работает только в CGI и CLI-режимах. Из-под апача — нельзя. Логично.

Демонизация



Чтобы демонизировать скрипт, нужно отвязать его от консоли и пустить в бесконечный цикл. Давай посмотрим, как это делается.

// создаем дочерний процесс
$child_pid = pcntl_fork();

if( $child_pid ) {
    // выходим из родительского, привязанного к консоли, процесса
    exit;  
}

// делаем основным процессом дочерний. 
// После этого он тоже может плодить детей. 
// Суровая жизнь у этих процессов... 
posix_setsid();


После таких действий мы остаемся с демоном — программой без консоли. Чтобы она не завершила свое выполнение немедленно, пускаем ее в бесконечный цикл (ну, почти):

while (!$stop_server) {
    //TODO: делаем что-то
}


Дочерние процессы



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

$child_processes = array();

while (!$stop_server) {
    if (!$stop_server and (count($child_processes) < MAX_CHILD_PROCESSES)) {
        //TODO: получаем задачу
        //плодим дочерний процесс
        $pid = pcntl_fork();
        if ($pid == -1) {
            //TODO: ошибка - не смогли создать процесс
        } elseif ($pid) {
            //процесс создан
            $child_processes[$pid] = true;
        } else {
            $pid = getmypid();
            //TODO: дочерний процесс - тут рабочая нагрузка
            exit;
        }
    } else {
        //чтоб не гонять цикл вхолостую
        sleep(SOME_DELAY); 
    }
    //проверяем, умер ли один из детей
    while ($signaled_pid = pcntl_waitpid(-1, $status, WNOHANG)) {
        if ($signaled_pid == -1) {
            //детей не осталось
            $child_processes = array();
            break;
        } else {
            unset($child_processes[$signaled_pid]);
        }
    }
} 

Обработка сигналов



Следующая по важности задача — обеспечение обработки сигналов. Сейчас наш демон ничего не знает о внешнем мире, и убить его можно только завершением процесса через kill -SIGKILL. Это плохо. Это очень плохо — SIGKILL прервет процессы на середине. Кроме того, ему никак нельзя передать информацию.

Есть куча интересных сигналов, которые можно обрабатывать, но мы остановимся на SIGTERM — сигнале корретного завершения работы.

//Без этой директивы PHP не будет перехватывать сигналы
declare(ticks=1);

//Обработчик
function sigHandler($signo) {
    global $stop_server;
    switch($signo) {
        case SIGTERM: {
            $stop_server = true;
            break;
        }
        default: {
            //все остальные сигналы
        }
    }
}
//регистрируем обработчик
pcntl_signal(SIGTERM, "sig_handler");


Вот и все. Мы перехватываем сигнал — ставим флаг в скрипте — используем этот флаг, чтоб не запускать новые потоки и завершить основной цикл.

Поддержание уникальности демона


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

function isDaemonActive($pid_file) {
    if( is_file($pid_file) ) {
        $pid = file_get_contents($pid_file);
        //проверяем на наличие процесса
        if(posix_kill($pid,0)) {
            //демон уже запущен
            return true;
        } else {
            //pid-файл есть, но процесса нет 
            if(!unlink($pid_file)) {
                //не могу уничтожить pid-файл. ошибка
                exit(-1);
            }
        }
    }
    return false;
}

if (isDaemonActive('/tmp/my_pid_file.pid')) {
    echo 'Daemon already active';
    exit;
}


А после демонизации — нужно записать в pid-файл текущий PID демона.

file_put_contents('/tmp/my_pid_file.pid', getmypid());


Вот и все, что нужно знать для написания демонов на PHP. Я не рассказывал об общем доступе к ресурсам, потому что эта проблема шире, чем написание демонов.

Удачи!

Статья с подсветкой синтаксиса — на моем блоге.
+83
20 сентября 2008, 13:53
323

комментарии (117)

0
aleks_raiden #
Отлично, спасибо! как раз столкнулся с задачей, где это очень нужно!
0
sneep39 #
Автор, планируете про общий доступ у ресурсам написать второй статьей?
0
coldFlame #
Будет время — напишу
0
Sov1et #
Было бы очень интересно.
0
Zenzen #
Поддерживаю.
+6
mystdeim #
В чём преимущество писать демоны на PHP?
Вы пишете: «Задачи: Выполнение трудоемких фоновых задач», здесь как раз и нужно использовать С/С++.
Я PHP конечно люблю, но так бы извращаться не стал. :)

P.S. За старания +.
+5
coldFlame #
Речь идет о демонах в составе сайта, то есть, вторичных по отношению к сайту, то есть, таких, в которых удобно использовать фреймворк, использованный на самом сайте.

Вот и преимущество.
+1
sovnarkom #
ммм, систему мгновенного обмена сообщениями можно состряпать, а уж сколько всякого интересного с кешированием можно напридумывать, удобно.

Жаль… очень жаль, что хостеры ещё не скоро это разрешат.
0
0x62ash #
VPS'ы покупайте, стоят не дорога и делайте что хотите.
0
sovnarkom #
Да это ясен пень, но дороже чем обычный хостинг несколько.
Хотя вообще, если проекту требуются такие демоны… то на обычном хостинге глупо его хостить.
+1
0x62ash #
имхо любой мало-мальски серьезный проект требует VPS
вот мой домашний проектик полностью грузит 4х ядерную систему с 6-ю гигами памяти 8-)
+2
sovnarkom #
Домашний… ммм… это как домашний тигр наверное или даже аллигатор)

Новичкам будет сложнее осваивать эту технологию, мало примеров будет работающих.
Postgres стал более доступен и больше статей про его использование появилось.
0
0x62ash #
Ну… рано или поздно, если проект успешный, новички мигрируют на VPS.

Да… этот домашний тигр рос маленьким котенком, потом кто-то из друзей попросил доступ, потом их друзья подключились, а теперь 25к уников лазиет на мой проектик )
0
kurokikaze #
Фреймворк, висящий в памяти в виде демона не слишком ли много отожрёт?
0
sovnarkom #
а сколько он отожрёт?
0
kurokikaze #
По размеру инклудов фреймворка?
0
develop7 #
Можно пользовать APC, к примеру.
0
develop7 #
Можно пользовать APC, к примеру.
0
develop7 #
Можно пользовать APC, к примеру.
0
junqed #
А при чем здесь фреймворк? В памяти будет висеть один скрипт-демон
0
kurokikaze #
Речь идет о демонах в составе сайта, то есть, вторичных по отношению к сайту, то есть, таких, в которых удобно использовать фреймворк, использованный на самом сайте.


Я вот об этом. Там внизу про это тоже пишут.
0
junqed #
ИМХО если нужен легкий демон — то средствами фреймворка лучше пользоваться, написать реализацию самому :)
+2
coldFlame #
Во-первых, в 5.3 появился достойный сборщик мусора.
Во-вторых, это зависит от того, как писался демон. Отжирать память может любой скрипт на любом языке.
+3
nIx0iD #
Отличная статья.
Пока что этого:

$pid = pcntl_fork();
if ($pid == -1) {
//ошибка
} elseif ($pid) {
//сюда попадет родительский процесс
} else {
//а сюда — дочерний процесс
}
//а сюда попадут оба процесса

для моих целей вполне хватало, но автор все очень толково расписал.

Кстати, хочу предупредить: если в программе есть ресурсы соединения с БД, то перед ветвлением их лучше закрыть, и в дочерних процессах открывать свои, которые должны завершаться в конце жизни процессов.
0
wayly #
Вот, наконец-то… А то задрали снизу с «многопоточностью» )))
То, о чем и говорили — демонизация и раздача заданий рулит ;)
0
phpdude #
неплохая статья, дочитывать не стал, просто добавил в избранное. автор молодец, толково описал

спасибо. может когда нить пригодится, хотя я больше любл писать на си если уж на то пошло ))

кстати почему бы просто не запустить демона в виде «php /path/to/script &» ?? ведь вы проделали тоже самое на сколько я понял :)
+1
phpdude #
точнее так

nohup php /path/to/script &
0
config #
и как потом чтоб остановить процесс, если это понадобится?
0
phpdude #
kill никто не отменял :)
0
config #
я так и думал что вы так ответите. как килять будем? по имени скрипта? или может ps а потом по id процесса?
0
phpdude #
ну например при запуске скрипта он свой ид складывает в файлик.

потом можем по айди, можно и по грепу от пс ах.

вариантов куча, исходя из задачи решения могут быть разные

просто я сказал то, что есть же готовые решения для таких задач, почему бы их не использовать? ))

половина линукса на нохуп + амперсанд работает, почему пхп скрипт должен выбиваться из этой пачки? не понимаю :)
0
nIx0iD #
Кстати, если нужно хапустить такой «демон» по какому-либо событию с сайта (например, по нажатию кнопки), чтобы он не завершился при закрытии странины в браузере, можно сделать так:
pclose(popen($exec,'r'));
где в $exec будет строка типа «php-cgi /path/to/php/script.php»
+1
coldFlame #
проблемка — если эту кнопку нажмет 100 людей одновременно, ваш сервер умрет. Нужна очередь.
0
nIx0iD #
Это просто пример того, как запускать скрипт. А в скрипте уже можут быть реализована и очередь, и что угодно.
0
AlexKuk #
Спасибо! Жду еще статей ;)
0
ocnk #
Однозначно в избранное! Все толково разжованно. Что то поднобное делал для мыльной рассылки, но без многопоточности.
–1
Kiriyama #
Вы выросли из PHP. Вам пора переходить на Python/Ruby.
0
prodd #
что руби и питон сложнее?:)
0
Kiriyama #
напротив :) Впрочем, вы просто попробуйте, и сами меня прекрасно поймёте. Через месяц PHP будет казаться экспонатом кунсткамеры.
+2
prodd #
по-моему вы не заметили мой сарказм:) просто почемуто в вашем комментарии создается впечатление что пхп это некий начальный простой этап, не вижу смысла его проходить если можно начать сразу с питона, при этом даже никогда не заниматся веб-разработкой
–1
Kiriyama #
вечером с юмором туго :) Я не хотел показать PHP начальным этапом. Жаль, если так вышло. Учебно-воспитательный эффект от него сильно негативный. Но, увы, у многих он стал первым. И больно смотреть, как через несколько лет, уже взрослые люди пытаются этой корягой решить задачи, для которых она совершенно не годится. Нет, решить-то конечно можно, но… это всё равно что строить из ДСП плотины ГЭС или танки из пенопласта.
+4
vintikzzz #
Главное чтобы руки росли из грамотных мест, а на чем писать вопрос уже вторичный Одну и ту же бизнес логику можно описать на любом из серверных языков, цена вопроса +- 10 строк. Что такого можно написать на ruby или python чего нельзя написать на php… Я так понимаю php не может быть крутым, только потому что на нем пишет ну очень много народа!
–3
Kiriyama #
Про руки — согласен. Но, почему-то, все толковые PHP-программисты, которых я встречал, изначально писали на С++/Java/Pascal и близких языках, делая на них большие проекты. И напротив, среди тех, кто два-три года писал только на PHP и ничего другого в жизни не видел, я ещё не видел ни одного грамотного разработчика, способного правильно поставить и красиво решить проблему.

Я так понимаю php не может быть крутым, только потому что на нем пишет ну очень много народа!

Массовость языка PHP тут не при чём. Если уж на то пошло, C++ и Java — куда более массовые языки. Windows тоже массовый, и хотя он страшно крив, маркетинг своё дело сделал. С PHP случилось то же самое. Года четыре тому назад все СМИ как заведённые писали про «удивительно простой и замечательный язык». Модно было.

Про его разработку стоит сказать особо. Когда кому-то нужна была функция «выбрать из массива каждый второй элемент и просуммировать их» — она сразу добавлялась в ядро! Потом следовала функция «выбрать каждый третий элемент и перемножить», и так до бесконечности… Я до сих пор помню, как один из создателей PHP так и охарактеризовал процесс разработки: «Более-менее управляемый хаос». PHP- это язык без «стержня», без структуры, без проектирования, без целей и… без будущего. Я сам писал на PHP около 2 лет, поэтому могу быть объективным.

Но, как и всё массовое, сразу он со сцены не уйдёт. Слишком большие деньги вбуханы в проекты на нём. Слишком много разработчиков им кормится. Это его и похоронит. Потому что весь этот балласт не даст переродить язык. Здесь нет Линуса Торвальдса, который скажет «мы полностью переделываем работу с оборудованием, и баста!». Нет своей Sun, которая тщательно следила за архитектурой Java. Нет Страуструпа (C++). А есть только очень-очень-очень-очень много малоквалифицированных кодеров, и 2-3% серьёзных разработчиков, которым действительно всё равно на чём писать. Но как раз последние и не станут делать танки из пенопласта — они способны использовать лучшие инструменты.
+3
xllx #
PHP- это язык … без будущего. Я сам писал на PHP около 2 лет, поэтому могу быть объективным.
Очень сомневаюсь в Вашей объективности относительно будущего PHP, да и 2 года весьма короткий срок для таких утверждений. На мой взгляд, с PHP все будет хорошо.
–1
Kiriyama #
Сомневайтесь, ваше право. Давайте только не переходить на личности. До PHP мне довелось много на чём писать, поэтому, когда я столкнулся с PHP, у меня уже было с чем сравнивать. И сравнение было не в пользу последнего.

А насчёт будущего — оно всех и рассудит. Лично я уверен, что доля PHP будет медленно, но неуклонно снижаться, если с языком не случится коренных перемен, которые перечеркнут всё его тёмное прошлое. Что мы сейчас и наблюдаем с Perl. И я описал, почему лично я сомневаюсь в возможности таких крутых перемен.
0
kex #
Ну, пхп, все ещё довольно простой и поэтому самый распространенный. В ближайшее время с ним ничего страшного не произойдет.

Тем не менее, все больше людей обращают внимания на преимущества других языков, таких как руби или питон, которые в свою очередь поддерживаются хостерами сейчас уже гораздо лучше чем даже в прошлом году.

Лично я предпочитаю не говорить о недостатках пхп, а стараюсь рассказывать достоинствах и отличиях того с чем работаю сам. Люди со временем сами будут делать выбор.

+3
AmdY #
недавно ходил на собеседование, как раз спрашивали о переходе на руби. т.к. на работу мне как-то параллельно, не стал подлизываться и сказал, что после близкого знакомства с руби мне как-то расхотелось. почему? я могу сделать на пыхе всё тоже что и на руби и немножко больше. тех. деректор думал как и я.
этап когда руби было модно уже прошёл. это видно даже по зарплатам.
ну а для нетепичных для вэб языка задач, действительно, иногда лучше использовать Python, потому как php ещё не готов. но руби никуда не годится.
P.S. Минусуя аргументируйте, задрала мне гигемония ubunta/firefox/mac/ruby
0
Kiriyama #
А почему минусующие должны аргументировать, а вы — нет? Если прямо сейчас вы PHP знаете лучше, разве это повод ругать то, в чём не разбираетесь? Я вот знаю русский язык лучше всего, но не заявляю, что английский — паршив, только потому, что не могу на нём также красиво выражаться.
0
AmdY #
кажется, не я начал эту ветку. а лишь спорил с необосновонность начального утверждения.
моя аргументация в посте выше — познакомившись с руби поближе, я сделал выводы, что на php могу сделать тоже самое. какой тогда смысл менять язык со всеми наработками.
помню, меня хотели впечатлить роликом с быстрой разработкой фотогаллереии, но используя свои наработки я и так делаю такую же меньше чем за 5 минут.
вот в освоении пайтон я вижу смысл, так как он не только вэб язык и может дополнить php.
0
coldFlame #
«come to the dark side, we have cookies?» :)

Честно говоря, если учесть, что я уже перешел на haml и sass, до руби недалеко.

Пока что испытываю панический страх, что все, освоенное мной в плане ПХП, станет ненужным.
+1
phpdude #
вы изучаете пхп ради теории? :)

если да, то оо вам пригодится, чем больше знаешь, тем проще дальше.

как я тут где то слышал фразу мол «при большом опыте даже время простоя добавляет опыт» ИМХО правильная фраза, правда не близка к теме)
0
Kiriyama #
Не бойтесь, на тёмной стороне нет ничего страшного, всё очень даже здорово! :)

Я, например, безнадёжно влюблён в Django :) Два года его применяю, и всё это время не перестаю им восторгаться. За всю мою программистскую практику такого удовольствия в работе я не получал ни от одного инструмента. Очень рекомендую!
0
m4spam #
О, Джанго…
А вы спросите у пехепешников, как они используют пул подключений к БД.
НЛО прилетело и опубликовало эту надпись здесь
+1
Yara #
Похожее описывается в книге Дж. Шлосснейгла «Профессиональное программирование на PHP. (Adv. Php programming)». Там есть еще пару дополнительных примеров, касательно форкинга и создания демонов. Если интересно, то позже выложу код в блоге.
+1
zarincheg #
выполнение задач, которые длятся больше, чем время ожидания при HTTP-запросе (30 секунд);

Ну это легко можно поправить с помощью ini_set() или в php.ini
А вообще статья познавательная, хотя конечно, имхо, лучше такие штуки на сях писать =)
0
coldFlame #
нет, еще есть время ожидания браузера. Емнип, там жестко 30 секунд
0
Caesar #
есть настройка ignore_client_abort, которая запрещает прибивать процесс даже если браузер отвалился по таймауту.

Но, конечно, включать её ни в коем случае нельзя, по крайней мере не для обработки запросов от неавторизованной публики.
0
phpdude #
или еще проще в скрипте

set_time_limit(n) + php.net/ignore_user_abort
0
burunduk2 #
шикарно!
респект и уважуха.
0
skazkin #
Как у вас в PHP всё сложно с демонами-то=)
Не то, что в Perl, который в том числе и для этого существует=)
+1
coldFlame #
Жаль, что перл не существует для создания веб-приложений. А то цены б ему не было :)
0
skazkin #
Не понимаю — в чём сложность написать веб-приложение на Perl?=)
Примеров реализации — пруд пруди-)
0
homm #
> Не понимаю — в чём сложность написать веб-приложение на Perl?=)
Думаю в написании сложности нет, просто потом это и читать иногда нужно =)
0
skazkin #
Ну и тем более, кстати говоря — все, нужные по работе веб приложения, я пишу именно на Perl — чтобы не смешивать, так сказать=) Порой получается быстрее — да и расслабляться не приходится — интересней)
0
phpdude #
не желаете?

perl -e '$?? s:; s: s;;$?:: s;;=]=>%-{
0
coldFlame #
а я все нужные демоны пишу на ПХП. Просто их меньше :)
0
homm #
Простите, что я еще не пытался искать сам, просто раз уж подвернулся случай — грех не спросить.

Как можно из PHP посылать сигналы сторонним процессам? Желательно без использований расширений, но возможно с запуском системных утилит.
0
coldFlame #
posix_kill($process_id, $signal);
0
phpdude #
`kill $pid`;

самый простой метод, если пхп не в сейфмоде работает :)
–3
kex #
Восьмидесяти этажные торговые центры с подземными парковками… из картонных коробок.

Знаю-знаю, не нравиться не нем… :)) сорре
0
ithilion #
В принципе, можно также «распараллелить» процесс, используя popen('php') с соответствующими параметрами, а потом обмениваться с ним информацией через сокеты.
0
makkintosh #
Я писал скрипты запускаемые при старте сервера или из консоли. цель этих скриптов был сбор хмл данных с разных источников и публикация полученных объявлений на подведомственном сайте. Работало не плохо :) вроде даже не текло как ни странно. (а может и текло, я тогда ещё не задумывался над такими вещами)
автору спасибо тем не менее :)
+3
Caesar #
Опечатка: «pcntl_fork возвращает дочернему процессу и PID дочернего процесса — родительскому». Так что же pcntl_fork возвращает дочернему процессу? (-:

Недочет:

В вашем варианте работы с pid_file'ом всё-ещё возможен одновременный запуск двух демонов. Чтобы этого избежать демон должен лочить пид-файл на запись в начале работы. Если это не удалось, то факт наличия существующего процесса можно даже не проверять — он точно есть, раз файл занят.

Дополнения:

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

Так, например, во фреймворке symfony экземпляры sfAggregateLogger никогда не удаляются из-за циклической ссылки (где-то через sfEventManager) — как результат получается утечка памяти. И файловых дескрипторов, если используются sfFileLogger'ы.

Таких примеров очень много.

Пути решения — либо исправлять фреймворк, либо ограничивать время жизни рабочего процесса, как это сделано в apache.

Ещё: полезно иметь управляющие скрипты, поддерживающие как минимум общепринятые юниксовые команды start и stop. Такие скрипты можно класть в rc.init (или rc.d) и таким образом обеспечить себе корректный подъём демонов при старте сервера и не менее корректное их завершение при выключении.

И ещё: не менее полезно перед началом любой работы переключаться в конкретную, определенную в конфигах рабочую директорию, дабы не плодить по файловой системе случайный/дебаговый вывод и не зависеть от того где в действительности был запущен демон.
–9
borman #
Абсолютно не залуживающая внимания тема. Во всех смыслах — исключительно академический интерес и наоборот, сосредоточение засилия быдлокодинга.

Такими темпами скоро на перл начнут модули ядра пробовать писать через прослойки и на дотнете драйвера для виндовс.

Если нужен многопоточный демон с автоподчисткой мусора — брать надо джаву. На худой конец питон. Но никак ни php. Еще немного, и критическая масса быдлокодеров начнет на нем пробовать писать игры=) Дайте же ему спокойно умереть, как устаревшему=)
+1
phpdude #
типичный ответ яваразработчика

сразу пришла мысль «скоро на яве начнут писать игры» всякие быдлоявапрограммеры :)
–3
maserg #
а так же модули ядра и драйвера для виндовс…

ибо на джаве быдлокодеров нет по-дефолту…
+1
phpdude #
я почти уверен что быдлокодеры есть всегда и везде, даже в евросети в догонку к топику про евросеть
0
maserg #
так я ж про тэ и пишу… а мне минусы от джавабыдлокодеров… отакэ…
+2
wayly #
Уважаемый, я вас огорчу: на любом языке можно реализовать любой функционал (исключая клиентские вещи). Даже ось можно написать на PHP. Не суть важно ;)

Другое дело — смешивание 2-х и более языков в приложении. Кому оно нужно? Любой PHP-разработчик встречает задачи, который в нативном PHP не предусмотрены. И решает эти задачи.

Любой разработчик встречает задачи, которые в его нативном языке не предусмотрены. А демон на Java — это не меньший изврат, кстати ;)

ЗЫ: есть куча примеров Online-игр написанных на PHP. Все быдлокодеры?: D: D: D
+1
phpdude #
я бы даже добавил что эти игры не тормозят, как игры на яве :-D

ибо все небыдлоявакодеры думают что ява бог производительности и гибкости, что в принципе неправильно.
0
wayly #
Я от таких яванебыдлокодеров даже статейку видел: www.codenet.ru/webmast/java/javavscpp.php
0
wayly #
Пля, отправил рано. ((
Суть в том, что НИ ОДИН ЧЕЛОВЕК из обсуждавших сию новость ни на коднете ни на лоре не согласился с результатами.

Так что не будем разводить холливар. А то достало уже показывать «небыдлокодерам» почему PHP не только отстоял свое право на жизнь у ASP.NET и JAVA в сфере Web, но и развивается нехило )))
0
phpdude #
пхп — хороший язык, гибкий, и для веба офигительно подходит, а если у тебя чтото с ним не получается, то «ты просто не умеешь его готовить» :)

пхп на уровне с яваскриптом = хорошие серверные и клиентские языки. хотя про тот же яваскрипт поговаривали что ему крындетс еще в далеких…
0
wayly #
phpdude, я за PHP, если что. А то выглядит как «учись готовить»: D
Просто вот для таких людей пишешь как заставить PHP работать быстрее, а они говорят, что экономия на спичках (это я про свой первый хабрапост «Работа со строками»): D
0
phpdude #
я за все языки если что, каждый имеет право на жизнь, есть вещи которые даже я использую, например эклипс, он вроде бы как на яве все еще, по крайней мере при последнем эклипсе все равно потребовалось ставить жре.

суть в том, что да, говоришь людям про оптимизацию, говришь и как в стену :(

если бы хватило кармы, я бы выложил ахуительный исходник по геотаргетингу на страну, по крайней мере, когда я это написал не было ничего подобного — 25 000 ип адресов в страны разрешает за 0.6 секунды, не хило? способна ли ява на такое, конечно способна, перл способен, даже какой нить визуалбейсик способен, даже на bash я думаю что такое можно реализовать, поэтому и говорю «надо только уметь готовить».

да и как пример, епт посмотрите на хабру, он же тоже на пхп оО и как он не утек весь в памяти, и в заданиях крона, наверное они тысячу серверов содержат тут… не иначе :)

зависть :)

сколько норм проектов написано на пхп?

а сколько на яве?
а сколько на.нет?

вконтакте на пхп, а у них нагрузка ой ой ой, думаю что даже небыдлоявакодеры нелегко таких скоростей бы добились.
–1
maserg #
а вышли мне сорцу плиз: maserg@gmail.com
0
phpdude #
выложил тут

gate.2315.ru/mygeo.rar

юзайте ))

может статью напишу как нить, когда кармы хватит :)
0
kibizoidus #
Будет более смешно, если на .net под Виндой начнут писать модули ядра под *nix.
Торвальдса хватит удар по дых…
+1
maserg #
просто «до кучи»

www.chabotc.com/phpsocketdaemon/

$daemon = new socketDaemon();
$server = $daemon->create_server('httpdServer', 'httpdServerClient', 0, 2001);
$daemon->process();

Performance:

Using apache bench (ab) on my home computer, using 256 concurrent, keep-alive requests over 50000 requests this server was able to serve over 4500(!) pages a second, and each page with a max latency of 0.15 ms. Yes i told you it was FAST didn't I?
0
developer #
Рассказать как мы это делали на принципе псевдо демонов, где управление через БД, а разделяемые ресурсы через мемкеш и БД?

Хотя, бывали задачи когда нужно что-то написать в виде функции на си, но это уж редкость скорее.
0
maserg #
да, конечно, расскажите плз
0
kibizoidus #
Хм… Ребята, давайте на PHP напишем PHP-машину, которая будет обрабатывать в реальном времени PHP, делать из него байткод и компилить в PHP. Ну заодно так же на PHP для PHP напишем компилятор PHP++. А почему бы и нет?

Все это к тому, что возможность написать что-то другое на PHP — это хорошо, но бездумно тратить ресурсы сервера такими задачами — нечто невообразимое.

Да, кстати — хоть кто-то делал бенчмаркинг такого решения по сравнению с форком на C/C++? Очень интересно будет посмотреть.

Статья хороша сама по себе как вводный курс в демонописание.
Но не на профильном языке для Web'а.
А то как-то совсем грустно — костыль на костыле для костыля с костылем…
0
coldFlame #
Я вот хотел вас удивить, что есть http-сервер, написанный на PHP, но у меня почему-то не открывается его сайт. :(

Насчет бенчмарка — а pcntl_fork это практически и есть никсовый fork(). Ну да, придется отфоркать весь интерпретатор, логично, но ведь интерпретатор — это программа на C, так что, по-моему, проигрыш в производительности компенсируется использованием привычного и удобного языка.

Самый ценный ресурс — время разработчика, не так ли?
0
coldFlame #
Я вот хотел вас удивить, что есть http-сервер, написанный на PHP, но у меня почему-то не открывается его сайт. :(

Насчет бенчмарка — а pcntl_fork это практически и есть никсовый fork(). Ну да, придется отфоркать весь интерпретатор, логично, но ведь интерпретатор — это программа на C, так что, по-моему, проигрыш в производительности компенсируется использованием привычного и удобного языка.

Самый ценный ресурс — время разработчика, не так ли?
0
kibizoidus #
Самый ценный ресурс — это знания и умения правильно применить полученные знания. Вы немного не с той стороны к процессу разработки подходите.
Сделать быстро — не значит сделать хорошо.
В то же самое время «Сделать хорошо на С» неравно «Сделать хорошо на PHP»

Если бы было так, то PHP уже давно бы писали на PHP, последовав иным примерам.
0
phpdude #
так то языки для разного.

напишите какой нить покрупнее сайтик на си пожалуйста для нас, хотя бы размером с небольшой форум, сколько времени у вас это займет?

неделю, год? месяц?
0
kibizoidus #
Будьте добры, не путайте божий дар с яичницей.
PHP — узкопрофильное решение. которое НИКОГДА не будет работать хорошо в чужой сфере.
Да, таки вы правы, протокол HTTP — это узкий профиль.
0
phpdude #
а вы случайно не на яве любите писать? :)
0
kibizoidus #
Нет, пишу на том же PHP. И считаю PHP узкопрофильным специализированным решением, которое отлично работает в свое области, но использовать его ВЕЗДЕ — разгильдяйство и излишество.
0
phpdude #
полностью согласен, просто в этой статье разговор о теории :) а не практике

имхо куда правильнее

nohup php /path/to/script &

чем использовать тот класс, который привел автор темы
0
kibizoidus #
nice -n 20 забыли
0
phpdude #
зависит от ситуации :)

может и -н 100 придется )))

суть в том что это более правильно, управляемо и просто это быстрее, к тому же это уже реализовано
0
kibizoidus #
Ошибочка. Максимальный n при ренайсе «19». «20» задано как следующее значение просто для красоты и простоты. Как-бы говорит «Дальше уже некуда» ^_^. Т.е. разницы при ренайсе -n 20 и -n 100 никакой.
Вы его просто редко используете или не используете вообще.
Но это частность примера.

А в общем, ИМХО, решение на PHP таких задач некорректно и ресурсоемко. Сам уже наступал на такие грабли.
0
phpdude #
я вас абсолютно понимаю :)
просто редко приходится иметь дело с найсом, уже не помню всех параметров ))

н = 100 просто было как… как показатель что часто нет общего решения задачи.

что на пхп вешать ресурсоемкие задачи неправильно — да. всегда делаю через нохап, ибо проще, выгоднее и удобнее как и гвоорил :)
0
coldFlame #
что-то я не пойму, как нохап — отдельная утилита — может быть проще чем чистый форк сразу после запуска скрипта.
0
phpdude #
мне проще :)

во вторых как то больше доверяю готовым средствам, проверенным годами, в третьх может не стоят экстеншн.

может чего то еще забыл.
0
lazycoder #
Таки использую на практике fork в пхп, могу сказать, что в условиях Continuous Integration оно гораздо удобнее, unix-way. По поводу того, течет или нет — это уж как напишете.

А вот с легкостью замасштабировать демон с 1 процесса до 10 заменой одной строчки кода + рестартить это всё деплой скриптом, написанным в те же две строчки — это весьма удобно.

Приходилось пользоваться как первым вариантом, так и вторым, с CI — форк удобнее однозначно.

По поводу экстеншенов — если сидите и пишете большой проект со своей инфраструктурой — это не проблема.
0
coldFlame #
какой класс?
0
yelbota #
а пару лет назад надо мою в ru_php смеялись когда я задвигал подобное. )
0
Snick #
Вместо sleep() используй usleep(). Так оно кошернее.
0
etc #
В своем время использовал popen ( string $command, string $mode ) для запуска нескольких демонов.

Перед этим должно пытался провертеть с помощью set_time_limit(0), т.к. хостинг позволял. Но долго бился головой, не знал почему скрипт убивается. Оказалось у апача есть еще свой тайм-аут. Соотв. скрипт, запущенный через апач убивается. Решил проблему так, что запускал через браузер скрипт, который запуск другие через popen мимо апача. Вроде работало.
0
valeraorg #
Несовсем понял про блокировку c pid-файлом. С каких делов процесс несможет удалить файл — вы же его нигде неблокируете. У вас про блокировку нислова. Или у меня где то дырка в фундаментальных знаниях. Статья супер спасибо.
0
coldFlame #
Это на всякий случай. А вообще такая ситуация будет, если запустить два демона из-под двух разных пользователей.
0
valeraorg #
Вы меня не поняли. Процесс аварийно завершился. А пид остался. Второй демон его удаляет и все хорошо. Но а если процесс не завершался а работает дальше при этом пид файл живет себе нормально, но он доступен на запись с другого потока, поскольку вы его не лочите. Второй демон спокойно удаляет этот пид и запускается.
0
coldFlame #
Так posix_kill и проверяет, запущен ли процесс по PIDу, записанному в файле.
0
Assargin #
Спасибо Вам наиогромнейшее!!!
Прочел Вашу статью, понял все с полпинка и написал демона, которого так не хватало нашему корпоративному серверу )) Все что нужно, чтобы понять, как же создаются демоны, и не только на PHP — в этой статье есть! А так как она про PHP — вообще роскошный подарок судьбы для меня ))
Причем написал я со всеми вытекающими типа start|stop|status|help, ну и все что у Вас в статье (за исключением, правда, многопроцессорности и многопоточности самого демона, это уже лишнее для меня в данном случае)

P.S.: где бы надыбать такую же хорошую статью по Drupal'у, чтобы самую-самую суть раскрывала, азы и принципы работа ядра и взаимодействия всего внутри самого двига, а то весь его дзен мне как-то недоступен пока )))

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.