HighLoad++

Конференция разработчиков
высоконагруженных систем

PHP-демоны

Программный комитет еще не принял решения по этому докладу
Александр Юдин (Cloud.ru — провайдер облачных и AI-технологий. Мы решаем задачи клиентов любого масштаба и предлагаем 80+ IaaS-, PaaS-сервисов и ML-платформу на базе уникальных суперкомпьютеров. В нашей команде 1 400 профессионалов, которые создают инновации и делают доступ к технологиям простым и удобным.)Александр Юдин

Php демоны - д.глазков
View more presentations from Ontico.

Меня зовут Денис Глазков, я работаю в компании "Badoo". Сегодня я вам расскажу про PHP-демоны.

Казалось бы, странно писать демоны на PHP, если у нас есть замечательный язык "Си". В принципе, все сервисы с сокетными соединениями и так реализуются на нем. Но все же есть некоторые плюсы создания и использования конкретно PHP-демонов.

Основные преимущества

Первое. Скорость разработки. У вас имеется слаженная команда PHP-разработчиков, определенные API-наработки, которые вы используете, код. Вы можете реализовать все это в виде демона и успешно использовать. Для того же самого эффекта на "Си" вам понадобилось бы создавать отдельную команду (она дороже, если что). В данном случае это скорость разработки.

Вы также можете быстро построить модель своего сервиса. У вас есть идея, как должен работать веб-сервис. Вы хотели бы его быстро проверить, посмотреть, как это будет. Не писать сложный код на "Си" и оттачивать его, а просто запустить на PHP и посмотреть. В принципе, этот код можно уже запустить на стадии производства (англ. "production"): он будет там работать.

Многие сервисы, которые я знаю, делали модель на PHP. В результате она использовалась на этапе производства долгое время.

Также на PHP есть много различных фреймворков, оберток, расширений (англ. extension) и прочего. Как я уже говорил, рынок разработчиков PHP широк. Все это вы можете использовать.

В отличие от некоторых языков, интерпретируемых в PHP, – "честное" выделение и чистка памяти. Если вы выделяете переменную или массив, под нее выделяется определенное количество памяти. При удалении эта память чистится: не происходит фоновой сборки «мусора», как это делается в некоторых языках. Вы действительно можете управлять той памятью, которую выделяете.

Где лучше применять PHP-демоны?

Спектр широк: от привычной нам веб-разработки до очень сложных сфер. Тут можно говорить об асинхронных сервисах, в основном это многопользовательские сервисы с мгновенным уведомлением клиенту или от клиента.

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

Это различного рода чаты, мессенджеры и тому подобное.

Недавно столкнулся с проблемой: был необходим сервер политик flash (англ. flash policy server). Если кто не в курсе, flash при инициализации прямого сокетного соединения всегда посылает на сервер определенного рода запрос и ожидает оттуда определенного рода ответ.

Быстро найти какое-то стандартное решение мне, к сожалению, не удалось. Тот же Engine X (nginx) поддерживает только HTTP-запросы, а не HTTP он уже не поддерживает.

Написали PHP-демон. Работает быстро и здорово.

В каких еще случаях применяются PHP-демоны? Существуют разного рода front-end-серверы, comet-серверы, какие-то оповещения и события на сайтах.

Также мы можем говорить о синхронных сервисах. Их тоже можно "демонизировать", реализовать в качестве отдельных. Это могут быть различные обработчики (англ. workers) какой-то логики. Они синхронные потому, что принимают запрос, обрабатывают его и возвращают результат.

Несколько запросов одновременно они не выполняют. Запросы в таком случае становятся в очередь. Это может быть очень удобно. Можно использовать это как кэш-сервер с очень сложной нетривиальной логикой. Например, информация о пользователе. Вы ее постоянно поддерживаете – она не подгружается из дополнительных сервисов, а все время находится… При отсоединении сервиса она удаляется.

Какие есть механизмы для асинхронной работы с сокетами (с асинхронным неблокирующим вводом/выводом на PHP)?

Их, собственно говоря, два. Есть нативный: socket_select. Он входит в стандартные библиотеки.

Есть libevent-механизм.

Расскажу об отличиях одного от другого.

Libevent. Была написана специальная библиотека на "Си". Вам не надо писать, затачиваясь под конкретную операционную систему – библиотека кроссплатформенная. Работает с такими механизмами, как kqueue, epoll, poll, /dev/poll. Предназначена эта библиотека для универсальной (англ. free based) ОС Linux и прочих ОС.

В отличие от socket_select у libevent нет полного пробегания по всем открытым сокетам. Socket_select пробегает по вашим открытым сокетам – смотрит, где же произошли изменения, формирует массив сокетов, на которых произошли изменения (чтение, запись или ошибка).

У libevent этого нет. Он работает чуть быстрее, чуть лучше в том плане, что показывает вам те сокеты, на которых произошли изменения, вызывая функцию обратного вызова (англ. callback).

Есть в libevent и еще одна удобная штука. Это организация буферов ввода/вывода. Эта библиотека берет на себя буфер ввода/вывода. Вы только пишете в буфер. Данные доходят дальше.

Если вы будете использовать подобный механизм в socket_select, то вам необходимо будет организовать поддержку буферов самостоятельно. Вы пишете что-то в сокет (сколько туда записалось). Данные могут записаться не полностью, а частично. Соответственно, оставшуюся часть вы должны где-то сохранить и потом переслать дальше.

Таким образом, libevent реализует удобный API и работает с функцией обратного вызова. Это удобно.

Есть расширение libevent на PHP: PECL-расширение, разработанное Антоном Довгалем (Antony Dovgal) – libevent.so. Он разработал много всяких расширений (в свое время он делал memcache и какие-то расширения для Oracle), создал общедоступный сервис для измерения производительности PHP (Pinba). Между прочим, сейчас он тоже работает в компании Badoo.

Запись и чтение происходит так же, как и на "Си", с использованием функции event_buffer_write/read. Все так же удобно работает, как и в "Си" с функцией обратного вызова, только вызываются PHP-шные функции обратного вызова.

Есть одна неплохая структура программной системы или, проще говоря, фреймворк, который использует данное расширение: PHPDaemon. Фреймворк предназначен для всех случаев жизни: есть как абстрактный синхронный сервер, так и готовые примеры. Допустим, примеры FastCGI-сервера, HTTP-сервера, pink-сервера. Очень много примеров.

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

Какие примеры архитектуры используют PHP-демоны?

Например, сервер front-end. Сервер держит соединение с несколькими сокетами одновременно.

Рассмотрим это на примере многопользовательской игры. У вас есть несколько клиентов, которые соединяются с сервером front-end через прямое сокетное соединение. Например, через flash-соединение или через веб-сокет-соединение. Единственное, чем занимается сервер front-end, это пересылает пакеты. Саму логику он не выполняет.

Логика выполняется чуть выше – на ваших обработчиках. Это могут быть также серверы PHP back-end, которые соединяются с сервером front-end тоже через сокетное соединение. В таких серверах может быть заключена какая-то сложная логика. Сервер PHP back-end работает с базой данных, с memcache, выполняет непосредственно логику.

Физически серверы PHP back-end могут быть расположены на разных машинах, необязательно на одной.

Клиент посылает запрос на сервер front-end. Далее он пересылает его на конкретный сервер back-end. Желательно, чтобы сервер front-end по логике мог назначать конкретному клиенту строго определенный сервер back-end. Это позволит держать информацию о вашем пользователе на конкретном сервере back-end постоянно. Серверы back-end постоянно хранят какую-то закэшированную информацию.

Информация о юзере будет держаться на этом сервере back-end. Соответственно, она не будет "размазана" между серверами back-end, и не будет лишних запросов к базе данных и memcache. В случае если клиент прекращает соединение, информация об этом пользователе с сервера back-end выгружается. 

Пришел запрос. Ваш сервер PHP back-end обработал его и вернул какой-то результат обратно серверу front-end, который, в свою очередь, направил его клиенту.

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

Когда один клиент меняет состояние, это должно отобразиться сразу у нескольких пользователей. Помимо того, что вы посылаете пакет с обратными данными, вы еще сообщаете адресата, до которого пакет должен в результате дойти. Сервер front-end "распарсит" этот пакет и отправит другим клиентам.

Существует схема, когда нет необходимости обрабатывать какую-то логику на серверах back-end. Например, это использование чатовых сообщений. Логика элементарная: нам надо просто послать чатовое сообщение конкретно какому-то  клиенту. Мы посылаем определенного рода команду на сервер front-end, он сразу ее адресует нужному клиенту, не затрагивая логику более высокого уровня.

Как я уже сказал, физически серверы back-end могут располагаться на разных машинах. Таким образом, есть возможность их масштабировать. Если на ваш сервер front-end приходится слишком большая нагрузка, и он перестает справляться с большим количеством соединений, можно масштабировать и серверы front-end. Их может быть несколько.

Схема будет примерно такая же. Главное – научить серверы front-end работать между собой или каким-то образом разделять их логически.

Рассмотрим классическую и наиболее популярную сейчас схему с comet на веб-сервере. Вы также можете написать свой PHP-демон в виде comet-сервера, который поддерживает постоянное соединение с вашими клиентами через веб-сокет.

В качестве сервера front-end при такой схеме выступает какой-то веб-сервер – например, nginx. Он, получая запрос, перенаправляет его на ваши обработчики. Они поддерживают связь с comet-сервером и в случае срабатывания какого-либо события посылают запрос comet-серверу, а тот доставляет его до клиентов. Может уведомлять как одного клиента, так и нескольких (это зависит от сложной логики).

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

Хотел поделиться одной проблемой, с которой я столкнулся при написании приложений с быстрым откликом.

Что подразумевается под приложением с быстрым откликом?

Это приложение, которое реагирует на какие-то события: например, движение мыши или набор клавиатуры.

Если в онлайн-игре вы рисуете или водите курсором, то же самое действие должно отображаться у других клиентов. Это и называется "быстрый отклик". Здесь идет речь о задержках в десятки миллисекунд.

Какова архитектура в этом случае?

Есть сервер, клиенты имеют прямое сокетное соединение. Один клиент водит курсором. По срабатыванию события ("move") мы передаем координаты движения курсора на сервер. Сервер это распределяет между клиентами. Он отдает те же самые пакеты обратно первому клиенту и другим. После этого происходит отображение – чтобы было по-честному. То есть он, в том числе, возвращает и первому клиенту.

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

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

Проблема: пакеты группируются в том случае, когда мы только пишем клиенту, когда сам клиент не пишет, как это обычно происходит. Мы что-то послали серверу – он вернул результат. В данной схеме этого не происходит. Решается эта проблема достаточно просто. Каждый клиент с какой-то периодичностью посылает на сервер небольшие пустые пакеты. Это может быть даже просто перенос строки.

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

Если вы решитесь писать демон на PHP, придется учесть некоторые особенности.

Что я называю "экономией на спичках"?

Обычно при разработке веб-приложений об этом никто не беспокоится. Во всех учебниках советуют не "экономить на спичках".

Рассмотрим операцию конкатенации строк. У вас есть три возможных варианта конкатенации строк.

Стандартный оператор конкатенации можно записать в несколько странном виде, поставив переменную в двойные кавычки. Можно использовать функцию sprintf – также конкатенировать ее со строкой. Получается, что наиболее быстрый вариант как раз неклассический: второй вариант в двойных кавычках.

Если вы проведете тесты производительности (англ. benchmark), то увидите, что этот вариант самый быстрый. Он рекомендуется к использованию.

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

Сравнение строк

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

Если говорить в целом, то обязательно нужно использовать тройное сравнение, то есть сравнение на тип. Оно работает чуть-чуть быстрее, чем двойное сравнение. Использовать "if else" вместо "switch". Использовать глобальные функции, не используя объектные – они работают чуть-чуть побыстрее. Желательно использовать короткие переменные вместо длинных.

Это все не классические подходы. Так обычно учитывать такие "мелочи" не рекомендуется, но для PHP-демонов это достаточно важно.

Вы должны постоянно проверять, какая операция работает быстрее. Тесты производительности - наше все!

Не забываем про банальную сборку мусора.

Напомню об очевидных вещах: необходимо закрывать дескрипторы и "чистить" замкнутые ссылки. Если объект А ссылается на объект Б, соответственно, объект Б ссылается на объект А. Как только вы о них забываете, они остаются в памяти, пока не будет вызван "сборщик мусора". При закрытии объекта лучше явно вычищать все свойства, используя оператор unset.

Не бойтесь использовать оператор unset! Даже если переменная уже не нужна, лучше вызвать unset. Причем не присваивать переменной новое значение (например, null или ноль), а именно использовать unset. Он будет явно вычищать память под эту переменную. 

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

Итог

Можно сказать, что в PHP имеются все возможности для написания полноценных демонов – сервисов с асинхронным вводом/выводом.

Если ваш демон написан с какой-то простой логикой, он будет ничуть не хуже своего аналога на "Си". Работает, в принципе, очень быстро, если учесть особенности, которые я перечислил.

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

Собственно, все. Жду вопросов!

 Вопросы и Ответы

Реплика из зала: Денис, ты сказал, что лучше чистить циклические ссылки вручную (с помощью unset). Не поможет ли в данном случае gc_collect_cycles, который появился в версии в 5.3? Все равно каждая итерация будет выполняться в цикле.

Денис Глазков: Имеется ввиду "сборщик мусора", Garbage Collector?

Реплика из зала: Да.

Денис Глазков: Если мы его вызываем, он тоже тратит какое-то время.

Реплика из зала: Это понятно. Вопрос бы в том, справляется ли он с циклическими ссылками...

Денис Глазков: Считается, что справляется. Да. Но лучше этого не делать. Как только вы начинаете вызывать Garbage Collector, у вас сервис работает-работает, а потом чик - начал вызывать "сборку мусора".  Такое бывает во многих языках, где "сборщик мусора" проходит фоново. Все, у вас демон подвис на какое-то время.

Реплика из зала: Вы сейчас сказали, что лучше использовать функции и не использовать классы. Фактически приложение на PHP не будет отличаться от обычного Си-шного приложения. Оно тоже будет замусорено глобальными функциями и прочей ерундой.

Денис Глазков: Не то что… Если есть возможность, то не использовать. Я не говорю – не использовать вообще. Конечно, можно использовать и объекты, и фреймворки. Но они чуть-чуть медленнее, только об этом речь.

Реплика из зала: Тогда какая разница?

Денис Глазков: Нет, можно использовать. Я при написании демонов использую объекты…

Реплика из зала: Понятно. Спасибо.

Денис Глазков: Все равно с объектами удобнее работать.

Реплика из зала: Здравствуйте! Большинство примеров, которые вы приводили, были относительно того, что демон принимает запросы.

Денис Глазков: Да.

Реплика из зала: Какие могут быть дополнительные рекомендации, например, для демона, который обрабатывает сообщения из очереди? Он висит, и ему не нужно быстро давать ответ. Просто ему надо медленно вытягивать из очереди сообщения и их обрабатывать. 

Денис Глазков: Собственно говоря, размер буфера увеличить, чтобы он у вас был готов к обработке. Или дополнительно ваш демон должен его логировать. Если обработка занимает какое-то время, может случиться так, что ваш буфер переполнится.

Реплика из зала: А по поводу работы с базой данных?

Денис Глазков: А что именно по поводу работы?

Реплика из зала: Держать постоянно соединение MySQL или каждый раз поднимать новый обработчик и соединяться с базой?

Денис Глазков: Вообще все эти схемы (архитектура которых была описана) "висят" постоянно. Они не выгружаются. Конечно, PHP не идеален. У него все равно будут утечки памяти и так далее. Как PHP в PM работает: он обрабатывает какое-то количество запросов, отмирает и рождается новый.

Здесь примерно схема та же самая. Он работает постоянно. Он держит постоянное соединение с базой данных, с memcache. Это, кстати, еще один из плюсов. Вам нет необходимости постоянно открывать соединение. У вас есть пул базы – они расшарены. Допустим, MySQL, несколько memcache. Вы открыли один раз соединение ко всем ним и держите его.

Соответственно, любой запрос… Он сразу же посылает запрос на базу. Эта схема лучше, чем в некоторых веб-запросах, когда постоянно происходит открытие соединения. Можно, конечно, использовать постоянное соединение (англ. persist connect), но в этом тоже есть некоторые подводные камни.

У нас был докладчик на HighLoad++, который рассказывал про постоянные соединения. Там есть очень много всяких подводных камней. Многие сервисы присылают запрос обратно, и вы не можете быть уверены, что полученный от базы данных результат – это ответ именно на ваш запрос. Это может быть и результат на предыдущую команду, если у вас отсох где-то…

Реплика из зала: Скажите, конкретно в проекте Badoo есть демоны, которые на PHP работают? Если есть, то какие.

Денис Глазков: В основном, конечно, как обработчики. Каких-то синхронных сервисов нет. У нас есть отдел Си-шников: он хорошо работает и пишет демоны на "Си". Я, скорее, об опыте использования таких демонов вообще говорил.

Реплика из зала: А какие именно обработчики?

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

Реплика из зала: Вы оценивали затраты ресурсов (англ. overhead) на количество? Сколько можно одновременно процессов запустить на одной машине, которые написаны, например, на PHP, и аналогичный по функциональности демон на "Си"?

Денис Глазков: Вы говорите именно про обработчики?

Реплика из зала: Да, именно про обработчики. Вопрос, связанный с запуском, с порождением дочерних процессов (сколько занимает) и с выгрузкой. Когда мы хотим "погасить" сотню обработчиков, сколько занимает этот процесс с учетом того, что освобождается вся память (отрабатывает машина PHP). Моменты старта и запуска, порождения и смерти.

Денис Глазков: Когда ваши обработчики умирают… Не знаю, один обработчик умер. Порождаются новые обработчики. Они не умирают.

Реплика из зала: Я имею ввиду оценку по времени.

Денис Глазков: Они умирают не все дружно, а постепенно – один отсох, другой тут же заменил его. Какой был до этого вопрос?

Реплика из зала: Запуск. Время запуска и время смерти именно обработчиков на PHP. Замеряли затраты ресурсов? Насколько хуже, чем запускаемые демоны на Си?

Денис Глазков: Не знаю, странно как-то сравнивать… Смотрите, мы запустили "голый" PHP, который вообще никакой логики не выполняет – эхо-сервер. Он сколько-то памяти уже потребляет. Аналогичный сервис на "Си" не будет потреблять памяти вообще. Можно ли тут сравнивать? Конечно, таких Си-шных демонов мы запустим больше. Сколько у вас PHP (ваш обработчик) весит, если аналогичная логика будет выполняться на "Си"?

Реплика из зала: Понятно, спасибо. Правильно я понимаю, что мораль такова – пишите на том языке, который дает наименьшие затраты ресурсов и вам больше привычен? Рекомендации общие достаточно. Они применимы ко всем.

Денис Глазков: Смысл доклада в целом – можно ли писать демоны на PHP. Они будут вполне хорошо себя проявлять даже в таких высоконагруженных проектах, как онлайн-игры. Тысячу одновременных соединений они вполне успешно держат. Если у вас не сильно сложная логика на сервере front-end, то PHP-демон будет ничуть не хуже Си-шного демона.

Аналогичные обработчики, которые будут стоять выше… Я не знаю, можно ли всю эту логику будет подогнать на "Си". Это работа с базой данных, с memcache и прочее. Все расширения, которые есть на PHP, также надо будет реализовать на "Си".

Выбираем, балансируем. Где проще писать – да, действительно. Смысл доклада в том, что это возможно. Оно работает хорошо.

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

Денис Глазков: Да.

Реплика из зала: При этом каждый новый запрос производит какую-то инициализацию. Создает структуры, объекты и так далее. Есть ли какой-то способ убрать эту трату ресурсов в демоне? Мы один раз инициализировались, а потом уже переходим через инициализацию при получении каждого нового запроса.

Денис Глазков: А этой инициализации и нет. Вы написали PHP-демон. Он сидит и слушает сокет. Все, что ему приходит, он обрабатывает, возвращая результат в этот же сокет. Инициализации не происходит. Он крутится в цикле постоянном, если условно.

Реплика из зала: Простите, я имел ввиду не инициализацию PHP как такового, а инициализацию внутри кода. Когда я кодом подгребаю под себя кучу данных, их для себя выстраиваю перед тем, как начать обработку и вкладывание в эти структуры данных, которые пришли внутри запроса. После этого только их обработка и отдача.

Имеется ввиду инициализация на уровне самого кода, а не приложения как такового. Понятно, что PHp-демон уже запущен…

Денис Глазков: Вы можете сократить, написав его более грамотно, что ли.

Реплика из зала: То есть, только изменение кода?

Денис Глазков: Да, изменение кода.

Реплика из зала: Вопрос технический – как правильно "гасить" демоны? Если мы, к примеру, поменяли код и хотим "загасить" демона, но при этом он ведет обработку?

Денис Глазков: На сервере front-end обычно, если мы рассматриваем схему, где к серверу front-end присоединены прямыми сокетными соединениями обработчики. Мы посылаем команду выгрузить все демоны. Он рассылает ее всем обработчикам. Те видят команду "shutdown". Он выгружается, и все. Его место занимает новый обработчик с новым кодом.

Реплика из зала: Вы говорите, у вас Си-шники работают хорошо. Какое-нибудь конкретное сравнение – конкретный демон, который был переписан на PHP. До и после есть данные?

Денис Глазков: Нет, в Badoo это особо не используется. Есть в другом проекте демон, который создавался, а потом был переписан на Си. Он потреблял меньше ресурсов процессора – раза в 2, наверное. Ну, и по памяти, конечно же. Но это мы говорим о какой-то несложной логике.

Реплика из зала: Как вы осуществляете обмен данных между обработчиками, мастером и так далее?

Денис Глазков: Вы можете какой-то свой формат придумать. Допустим, это JSON.

Реплика из зала: Придумать я могу. Да. Вы как-нибудь это делали?

Денис Глазков: Если от обработчика посылается пакет серверу front-end, то в самом начале еще должна быть какая-то информация для самого сервера front-end. Она должна быть в элементарном виде: ID клиента, которому надо послать, номер запроса, какой тип пакета он должен пересылать. Сервер front-end должен очень быстро обработать эту информацию. Самый тривиальный должен быть формат – без каких-либо сложностей.

Данные, которые мы посылаем конечному клиенту, дальше могут быть в JSON.

Реплика из зала: Я понял. Тогда немножко усложню вопрос. Допустим, я вешаю функцию обратного вызова на обработчики. Появляются "ready", "complete", "shutdown" и так далее.  При каждом обратном вызове мне нужно отослать мастеру какую-то информацию: я сделал, я завершил, я готов и так далее.

Денис Глазков: Вы имеете ввиду, что обработчик сообщает это?

Реплика из зала: Все верно.

Денис Глазков: Как только обработчик соединяется, он посылает первый пакет – я такой-то сервер back-end, у меня такой-то номер. Если что, обрабатываю таких-то клиентов, если надо. Все. Сервер front-end получает от него запрос.

Реплика из зала: Но мне надо отослать именно мастеру! У меня висит мастер, который управляет основным циклом и заведует всеми обработчиками. Мне надо оповестить мастера, что я завершил какой-то определенный цикл и на данном этапе хочу отдать ему информацию, чтобы он мне дал уведомление, стоит ли мне вообще дальше продолжать работу. На языках более низкого уровня все это проще делается.

Денис Глазков: Честно говоря, не понял проблему. Ну, висит ваш обработчик. Присоединился он к серверу front-end, послал ему сигнал "я готов". Сервер frontend его принял. Может, даже ответный какой-то сигнал отослал…

Реплика из зала: Ладно, хорошо. О сервере front-end. Прошу прощения, что перебиваю.

Денис Глазков: Что вы называете мастером?

Реплика из зала: Мастер-сервер. Как мы "форкаемся" в PHP? Мы запускаем fork, отцепляемся от консоли.

Денис Глазков: Я понял.

Реплика из зала: Запускается мастер-сервер. Дальше мы создаем какую-то коллекцию и храним там обработчики, грубо говоря. Верно? Ну, примерно так, если по-простому. Есть мастер-сервер, который всем заведует, чтобы не появлялись зомби-процессы и так далее. 

Денис Глазков: Если у вас будет распределено между машинами, то эта схема уже не будет работать.

Генеральный интернет-партнёр

  • Mail.Ru Group

Бронзовые спонсоры

  • http://www.google.com/

Бронзовые спонсоры

  • RUcenter

Официальный регистратор

  • http://domenus.ru/

Спонсор

  • http://firstdedic.ru/

Спонсор

  • http://www.1c-bitrix.ru/

Спонсор

  • Вadoo

Спонсор

  • http://www.cloudone.ru/

Генеральный медиа-партнёр

  • http://www.bfm.ru/

Генеральный информационный партнёр

  • http://www.nomobile.ru/

Генеральный HR-партнёр

  • HeadHunter

Фри-ланс партнёр

  • http://www.free-lance.ru/

Погодный партнёр

  • GISMETEO / ГИСМЕТЕО

Цветочный партнёр

  • http://www.funflowers.ru/

Интернет-магазин

  • SoftKey

Официальный партнёр

  • http://raec.ru/

Информационная поддержка

По любым вопросам обращайтесь:
Программный комитет : Олег Бунин , +7 (916) 635-95-84
Организационный комитет : Олег Бунин , +7 (916) 635-95-84
Бухгалтерия и вопросы оплаты : , +7(495) 646-07-68

Почтовый адрес: 119180, Москва, Бродников пер., д. 7 стр. 1, ООО «Онтико»

Rambler's Top100
Рейтинг@Mail.ru