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

полудух

Итсист
приветствую
изучаю вопрос буферов libevent...
есть такая замечательная документация от IBM на русском под C++
в ней написано:
1. Основные концепции
Идея относительно проста: данные помещаются в буфер (или извлекаются из буфера) в ответ на определённое событие, произошедшее на объекте, для которого был создан этот буфер.
т.е. буфер УЖЕ создан был

но тут человек изображает демона и к буферами подходит несколько иначе:
PHP:
$socket = stream_socket_server(“tcp://$IP:$port“, $errno, $errstr); //  наблюдаемый объект (дескриптор)
stream_set_blocking($socket, 0);                         //  устанавливаем в неблокируемый режим
event_set($event, $socket, EV_READ | EV_PERSIST, 'onAccept', $base);  // устанавливаем обработчик на дескриптор

function onAccept($socket, $flag, $base) { // функция обработчик на появление нового соединения
    global $id,$buffers,$ctx_connections;
$id++;
    $connection = stream_socket_accept($socket);
    stream_set_blocking($connection, 0);
    $buffer = event_buffer_new($connection, 'onRead', NULL, 'onError', $id); // создаем новый буфер и привязываемем  обработчики на чтение/запись в буфер или ошибку обработи.
    event_buffer_base_set($buffer, $base); // присоединяем буфер к базовому контексту
    event_buffer_enable($buffer, EV_READ | EV_PERSIST); // устанавливаем флаги
    $ctx_connections[$id] = $connection;
    $buffers[$id] = $buffer;
}
собственно, он создаёт новый буфер на каждое подключение
$buffer = event_buffer_new($connection, 'onRead', NULL, 'onError', $id); // создаем новый буфер и привязываемем обработчики на чтение/запись в буфер или ошибку обработи.
что идёт несколько вразрез с логикой и документацией от IBM
правильно то было бы создать буфер 1 раз под конкретный сокет, а дальше просто снимать с него данные

поэтому ИЩУ ИСТИНУ с вашей помощью ) поясните, как должно быть

а ещё такой вопрос: если у меня ожидаются редкие подключения с передачей ~20 байт (команда демону)
нужны мне эти буферы вообще?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
собственно, он создаёт новый буфер на каждое подключение

что идёт несколько вразрез с логикой и документацией от IBM
правильно то было бы создать буфер 1 раз под конкретный сокет, а дальше просто снимать с него данные

поэтому ИЩУ ИСТИНУ с вашей помощью ) поясните, как должно быть

а ещё такой вопрос: если у меня ожидаются редкие подключения с передачей ~20 байт (команда демону)
нужны мне эти буферы вообще?
Он и создает по одному буферу на каждой сокет клиентского подключения. Если ты будешь пользоваться одним буфером для всех подключений, ты не сможешь разграничить подключившихся клиентов.
 

MiksIr

miksir@home:~$
правильно то было бы создать буфер 1 раз под конкретный сокет, а дальше просто снимать с него данные
Каждое новое соединение = новый сокет.

а ещё такой вопрос: если у меня ожидаются редкие подключения с передачей ~20 байт (команда демону)
нужны мне эти буферы вообще?
Скорее всего нет, еще есть IO буфер операционной системы и обычно он больше 20 байт.
 

полудух

Итсист
Он и создает по одному буферу на каждой сокет клиентского подключения. Если ты будешь пользоваться одним буфером для всех подключений, ты не сможешь разграничить подключившихся клиентов.
ну значит, если у меня клиент подключается, передаёт свои 30 байт и тут же отключается, смысла в буфере нет?

а вообще о каких клиентах речь, если у меня локалхост? там все подключения идут от пхп-скрипта с веб-сервера
 

полудух

Итсист
нет никакой разницы, внутри одного компьютера или снаружи, tcp стек один для всех. Клиент - это все, что снаружи демона и приходит к нему.
да это понятно
речь о том, что нафига мне их разделять, если у меня 1 клиент?
 

HORO

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

флоппик

promotor fidei
Команда форума
Партнер клуба
Если у тебя одно подключение, тебе не нужны событийные буферы в принципе.
 

MiksIr

miksir@home:~$
Если у вас 1 клиент, вам вообще неблокирующая ассинхронность не нужна. Вот минимум что нужен.
PHP:
<?php

$socket = stream_socket_server("tcp://127.0.0.1:12345");

while ($connect = stream_socket_accept($socket, -1)) {
    $request = fread($connect, 20);
    $answer = do_something($request);
    fwrite($connect, $answer);
    fclose($connect);
}

fclose($socket);
 

полудух

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

MiksIr

miksir@home:~$
Клиент - это не в магазине. Клиент - это подключение. Если один процесс веб-сервера делает 1000 одновременных соединений на ваш демон - у демона 1000 клиентов. Это очевидно ибо демон и вы, как его автор, в принципе не можете знать - от одного процесса пришли соединения или от 100 разных. Одно входящее соединение называется 1-м клиентом. А кто их там генерит - никого заботить не должно.
 

полудух

Итсист
Клиент - это не в магазине. Клиент - это подключение. Если один процесс веб-сервера делает 1000 одновременных соединений на ваш демон - у демона 1000 клиентов. Это очевидно ибо демон и вы, как его автор, в принципе не можете знать - от одного процесса пришли соединения или от 100 разных. Одно входящее соединение называется 1-м клиентом. А кто их там генерит - никого заботить не должно.
согласен
значит буферы всё-таки нужны
и таки на каждое такое подключение надо таки делать отдельный буфер каждый раз?
 

MiksIr

miksir@home:~$
Для решения способа обработки нужно ответ на вопрос - сколько клиентов будет _одновременно_. Если у вас равномерно идет 100 входящих соединений в секунду минуту, а вы обрабатываете каждое за 20 мс, вам паралелльность нафиг не нужна. Если 1000 входящих соединений - вы уже поочереди обслужить их не успеете, нужно обрабатывать параллельно.
 

полудух

Итсист
Для решения способа обработки нужно ответ на вопрос - сколько клиентов будет _одновременно_. Если у вас равномерно идет 100 входящих соединений в секунду, а вы обрабатываете каждое за 20 мс, вам паралелльность нафиг не нужна. Если 1000 выходящих соединений - вы уже поочереди обслужить их не успеете, нужно обрабатывать параллельно.
демону кидается строка типа 1_283844_228324_22
он по этой команде форкает в бэкграунд соответствующую задачу и забывает про неё
 

MiksIr

miksir@home:~$
Если у вас форк-схема, то libevent вам не нужен. Нужно замерить время на форк и оценить, сколько запросов в секунду сможете обработать. Если устраивает - то берете мой вариант выше и приделываете туда форк.
 

полудух

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

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

upd: в общем сам понял, что libevent позволяет именно 1000 подключений разом схватать, а не по очереди, это и есть параллельность

но в целом он всё-равно удобнее со своим обработчиками и собственным event_base_loop, без while
 
Последнее редактирование:
Сверху