кто-то делал PHP-демоны на базе libevent ?

fixxxer

К.О.
Партнер клуба
Я тебе уже два раза объяснил.Перечитай.

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

Breeze

goshogun
Команда форума
Партнер клуба
программа выполняет несколько задач одновременно попеременно
не, те процессы, которые там запускаются, выполняются как раз параллельно(веб сервер, например, обрабатывает запросы), это и сбивает с толку, типа это stream_select такой параллельный, хотя таски на выполнение ставятся последовательно, как и результат обрабатывается по очереди пусть и не в том порядке, в котором запущено, что тоже воспринимается как параллельная работа самого скрипта и заслуга stream_select :)
 

MiksIr

miksir@home:~$
не, те процессы, которые там запускаются, выполняются как раз параллельно
Процессы там во втором примере запускаются. А тут у человека затык прям на первом примере. Где ничего не запускается и голый мультиплекс.
 

полудух

Итсист
типа это stream_select такой параллельный, хотя таски на выполнение ставятся последовательно, как и результат обрабатывается по очереди пусть и не в том порядке
таки результат с тобой не согласен:
Program starts at 02:38:50.
Stream 4 closes at 02:38:53.
Stream 3 closes at 02:38:56.
Stream 2 closes at 02:38:59.
Stream 1 closes at 02:39:02.
Stream 0 closes at 02:39:05.
это 5 подключений, выполненных одновременно
ну возможно это только к сокетам применимо, но работает же
Запрошенные Web-страницы возвращают результаты после переменной задержки, показанной ниже. Если бы программа выполняла запросы последовательно, для ее завершения понадобилось бы около 15+12+9+6+3 (45) секунд. Как показано в листинге 2, на самом деле она завершается за 15 секунд. Утроение производительности - это отличный результат.

Такое стало возможно благодаря stream_select - новой функции в PHP V5. Запросы инициируются обычным способом - открытием нескольких stream_socket_clients и написанием GET к каждому из них
 

MiksIr

miksir@home:~$
99% времени, указанного в статье, программа не делает ничего. А только ждет. Ускорение как раз и получается потому, что происходит одновременное ожидаение.
Простой пример. Программа ждет ответ от удаленного сервера 10 секунд и 1 секунду что-то с ним делает (читает, анализирует, пишет в файл). И есть 5 запросов.
Последовательно будет 10*5 + 1*5. С помощью мультиплексирования (select) будет 10 + 1*5. Т.е. мы одновременно ждем ответ от 5 соединений, а когда он приходит - все-равно тратим по 1 секунде обработки на каждого.
Легко понять, что в таком режиме будет очень мало смысла, если вы тратите на ожидание ответа от второй стороны 1 секунду, а PHP код обрабатывающи эти данные работает 10 секунд.
 

fixxxer

К.О.
Партнер клуба
таки результат с тобой не согласен
Хватит тупить.
PHP:
$queue = [
    ['a', 5],
    ['b', 3],
    ['c', 2],
    ['d', 4],
    ['e', 1],
];

$start = time();

while ($element = array_shift($queue)) {
    if ($start + $element[1] >= time()) {
        $queue[] = $element;
    } else {
        echo "Finished: {$element[0]}\n";
    }
    usleep(1000);
}
Это, по-твоему, "одновременно"?
 

полудух

Итсист
спасибо.
не буду спорить со спецами, вероятность выше, что я пока не до конца въезжаю. это темя для меня всё-таки новая

появилась грабля поважнее: внутри libevent onAccept форки виснут почему-то.. отрабатывают, но виснут. т.е. можно закинуть несколько команд в сокет и они все отработают, а вот следующие команды сокет уже не принимает. телнетом проверял, он просто зависает после перевода строки, а должен сразу закрываться.
вообще onAccept уже поздно форкать, надо было раньше, как я потом допёр...
но раньше сам libevent стоит, который при этом threads не умеет
короче, у меня задача, из веба создавать юзеров в системе, а потом ещё архив развернуть к ним в хомяки например (по времени занимает сек 30)
и может быть более 1 за раз, т.е. одновременно
у меня сомнения, что юзеров в системе можно делать одновременно всех, потому что там useradd берёт ~1 секунду на процесс и файл /etc/passwd он 1, как и остальные /etc/shadow итд
но вот архив распаковать надо как-то суметь сразу все
при этом нельзя просто в БГ скинуть, надо получить сигнал об успешном завершении и сделать запись в БД (вот этот момент особенной проработки требует.. там может флаг какой в memcached вешать?)
как такое лучше сделать? как тут советовали, без всяких libevent?
может где почитать можно про организацию хостинга с т.з. тех.деталей именно таких, глубоких?
а то везде всякие cPanel'и и ISP "описывают"
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Сделай ОЧЕРЕДЬ заданий. Хоть кроном. Тебе в принципе не нужна вообще никакая параллельность для этой задачи.
 

полудух

Итсист
кроном уже делал, х*йня получается
надо мгновенно - кнопку нажал - результат получил
очередь тоже не. надо сразу всем
 

fixxxer

К.О.
Партнер клуба
а форкаться на каждый элемент очереди религия запрещает?
 

полудух

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

fixxxer

К.О.
Партнер клуба
Попробую объяснить доступно)

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

Варианты:

1) добавляем еще 5 таких же - это префорк с 5 воркерами
2) нанимаем 65535 таджиков и вызываем по одному обслуживать каждого очередного покупателя - это форк на каждый процесс. При большом числе таджиков они будут блокироваться на недостатке ресурсов (количество касс, кухня)
3) нанимаем людей на кухню (по префорк модели), оставляем одного кассира, кассир ждет готовности каждого заказа, пока не будет готов - следующего обслуживать не может. Тут кухня - это префорк-модель, а на кассе - тупой последовательный процесс, что неэффективно
3.1) нанимаем еще 5 людей на кассу, которые ведут себя так же как в п.3 - это префорк
3.2) один кассир говорит "ждите заказа" и принимает следующий, по мере готовности кладет на поднос - это на кассе либевент
3.3) по варианту 3.2 нанимаем 5 людей, это префорк, в каждом воркере - либевент
 

полудух

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

fixxxer

К.О.
Партнер клуба
Нет. Он же не сам готовит на кухне, а просто передает туда заказ и ждет готовности. Вот если у тебя есть отдельный prefork демон занимающийся распаковкой архивов, а ему просто передается команда "распакуй мне 1.zip и скажи как будет готово" - тогда получится 3.2.
 

полудух

Итсист
ну вот с форком внутри onAccept есть проблема
поэтому я уже нашёл выход без форка )
правда теперь форк нужен для смены uid, но только за пределами onAccept
внутри callback какой-то другой мир...
оттуда ссылки нельзя передавать, например
 
Сверху