phpDaemon — фреймворк асинхронных приложений

    Сегодня речь пойдет о phpDaemon — асинхронном модульном демоне-фреймворке, который берёт на себя обработку I/O (libevent) и другие низкоуровневые задачи, присущие демонам. С его помощью легко писать правильные сетевые приложения с блэкджеком и шлюхами.
    Из коробки идут сервера FastCGI, HTTP, CGI, FlashPolicy, Telnet, WebSocket (!) — да-да тот самый волшебный пендаль новый протокол от Google. И клиенты mysql, memcached, mongodb… И многое другое, полный список под катом. Работать с сетью действительно просто. Программист средней руки может написать, к примеру, IRC-бота за считанные часы.
    В качестве наглядного примера я реализовал вот этот чат на phpDaemon + WebSocket + MongoDB + jQuery. Он наглядно демонстрирует преимущества этой технологии: доставка сообщений мгновенна, накладные расходы при обмене данными минимальны, высока производительность, приложение масштабируется горизонтально. Исходники этого чата (в данный момент 17 кб). Прошу заметить, чат тестировался и работает в Chrome, FF, IE6+, Iron, Safari.

    Где это лучше применить?


    Область применения phpDaemon очень широка как в Веб-разработке, так и за её пределами. С его помощью хорошо делать real-time многопользовательские игры (например на Flash), сервисы с мгновенным взаимодействием, чаты, IM-гейты… Также хорошо использовать необходимые в хозяйстве полезности, такие как сервер flashpolicy.
    Самое первое реальное применение проекта в production — мгновенная доставка личных сообщений: на страницах сайта был невидимый swf-файл (Flash) в несколько килобайт, он подключался к серверу и ждал команд. Как только пользователю приходило сообщения, Flash посылал команду странице (Javascript), который в свою очередь сразу же отображал всплывающую иконку и «пиликал». Мы с коллегами были поражены скоростью реакции, звук от соседнего компьютера был слышен еще до того как отправитель успевал оторвать палец от левой кнопки мыши.
    А совсем недавно по заказу был реализован сервер предоставляющий API к Asterisk'у (для IP-телефонии), прекрасно держит нагрузку.

    Архитектура и возможности


    Приложения в phpDaemon содержат лишь логику обработки, а все низкоуровневые вызовы происходят автоматически. Проект написан исключительно на PHP, и вы, вероятно уже задались вопросом производительности. I/O происходит через libevent, библиотеку хорошо зарекомендовавшую себя, которая используется в memcached и в других известных проектах. При этом, скорость выполнения инструкций в PHP весьма велика, он превосходит в этом многие другие языки своей группы. В привычных всем синхронных скриптах львиная доля времени уходит на запуск среды и на блокировку при вводе-выводе, например при запросе к базе данных обычный скрипт не продолжит выполнение пока ответ не будет получен. В phpDaemon таких блокировок нет: отослали запрос, повесили если нужно callback-функцию на ответ, и пошли по своим делам.

    phpDaemon — это 1 мастер-процесс и множество рабочих процессов, каждый из которых представляет собой среду выполнения приложений. Приложение является классом-наследником AppInstance, который описывает его реакцию на различные события. При запуске рабочих процессов, они создают экземпляры классов-приложений и выполняют метод init(). В методе init() приложение может забиндить сокет, куда-то подключиться, или открыть локальный дескриптор (при этом одно не исключает другого). Приложение также может взаимодействовать с другими приложениями в рабочем процессе, объявляя в них необходимые параметры: например, прописать роут в WebSocketServer.
    После того как оно забиндило сокет, при поступлении подходящих соединений будет вызвано событие onAccepted(connId,addr). Пример этого метода из WebSocketServer:
    public function onAccepted($connId,$addr)
    {
     $this->sessions[$connId] = new WebSocketSession($connId,$this);
     $this->sessions[$connId]->clientAddr = $addr;
    }


    * This source code was highlighted with Source Code Highlighter.

    Сервер отдающий политику crossdomain по 843 порту весит всего 1,67 кб — FlashPolicy.php. Между тем, его явное преимущество перед множеством аналогов очевидно: его нельзя положить открыв десяток-другой телнет-сессий. Многие популярные реализации flashpolicyd DoS-ятся открытием даже одной сессии, которая ничего не шлет, поскольку в них идёт синхронная обработка, и процесс ждет у моря погоды.

    Для обработки HTTP-запросов (в том числе по FastCGI) существует отдельная сущность — классы-наследники Request. Эта сущность имеет входные параметры (get,post,cookie,server...) и состояния — run/sleep/dead. Запросы висят в очереди, и диспетчер вызывает их по порядку. Если запросу не нужно прерываться, он может сделать всю работу и вернуть код завершения, чтобы диспетчер удалил его из очереди. Если запрос производит операции, требующие ожидания (например делает запрос к MongoDB), то ему необходимо сделать $this->sleep(30) чтобы заснуть максимум на 30 на секунд. А в callback-функции к запросу MongoDB достаточно указать $request->wakeup(), чтобы немедленно прогнать сон. Тогда диспетчер обратится к нему незамедлительно. Запрос сможет продолжить своё выполнение, имея ответ от MongoDB. Если же ответ по каким-то причинам не получен, запрос может вывести «We're sorry, try again shortly later». Для полного завершения запроса в методе run() вызывается либо return 1, либо $this->terminate().
    После того как заголовки запроса приняты приложения-сервера (коробочные — FastCGI, HTTP) обращаются к appResolver'у, который определяет к кому приложению поступает запрос и вызывает у приложения метод beginRequest. А он, в свою очередь, создает и возвращает экземпляр класса-наследника Request. Затем объект запроса кладется в очередь (queue). Приложение может по желанию добавлять в очередь и собственные «запросы» посредством метода pushRequest, это необходимо чтобы вызывать определенный код через задаваемые промежутки времени (например, это делается в MongoNode для опроса курсора).
    Запросами в полной мере поддерживаются POST-данные (и multipart), Upload'ы, и прочее (страничка-пример), более того — больше нет необходимости вручную обрабатывать UCS-2 кодировку в запросах (%uFFFF) — это происходит автоматически.
    Поддерживаются X-Sendfile (запись ответа на запроса веб-сервера в файл) и Request-Body-File (чтение body-часть запроса из файла). Можно начать выполнение запроса до того как тело полностью принято, и можно программировать обработку upload'а (например, кидать сразу в memcached, а не во временный файл на диске).

    Предвижу просьбы дать конкретные цифры показывающие выигрыш в производительности, но некорректно сравнивать синхронные и асинхронные фреймворки. Понятно что последние быстрее. Однако, разница будет напрямую зависеть от приложения, а именно — от количества и времени блокировок в синхронном варианте. Добавлю лишь субъективный бенчмарк странички-примера… Requests per second: 4784.80 [#/sec] (mean).
    В данный момент используется последняя стабильная версия libevent (1.4.10-stable), скоро будет выпущена libevent 2.0, это даст возможность рабочим процессам принимать соединения через epoll_wait и принесет дополнительный выигрыш в производительности перед текущим вариантом. Как только так сразу.

    Управляемость, администрирование, конфигурирование


    Встроенный управляющий скрипт:
    # phpd
    usage: phpd (start|(hard)stop|update|reload|(hard)restart|fullstatus|status|configtest|help)…

    # phpd fullstatus
    [STATUS] phpDaemon 0.2 is running (/var/run/phpdaemon.pid).
    State of workers:
    Total: 1
    Idle: 1
    Busy: 0
    Shutdown: 1
    Pre-init: 0
    Wait-init: 0
    Init: 0

    Рабочими процессами поддерживается команды suid, sgid, chroot. Они задаются на уровне конфигурации. Встроенный динамический MPM (Multi-Process Manager) определяет загруженность рабочих процессов и запускает новые в рамках настроек. Используя API, алгоритм MPM можно переопределить в конфигурационном файле. При разработке проекта делается упор как на расширяемость и заменяемость компонентов, так и на простоту использования.

    Искаропки


    На данный момент в дистрибутив включены следующие модули:
    • FastCGI — позволяет подключаться к приложениям по протоколу FastCGI.
    • HTTP — позволяет подключаться к приложениям по HTTP.
    • CGI — позволяет пускать обычные CGI-приложения по FastCGI, HTTP и любым другим транспортам.
    • Flashpolicy — раздает политику crossdomain для Flash по 843 порту.
    • WebSocketServer — обслуживает WebSocket-сеансы.
    • MongoClient — драйвер MongoDB.
    • MySQLClient — драйвер MySQL (через него также можно подключаться к SphinxQL).
    • MySQLProxy — проксирующий MySQL-сервер.
    • MongoNode — реализация slave-ноды MongoDB, позволяет вешать события на изменения объектов в базе.
    • MemcacheClient — драйвер Memcache.
    • LockServer — распределенный сервис блокировок.
    • LockClient — клиент для собственного сервиса блокировок.
    • TelnetHoneypot — простейший сервер telnet.
    • RTEPServer/RTEPClient — реализация Real-Time Events Protocol, позволяющая клиентам подписываться на события и анонсировать их.
    • BitTorrentTracker — трекер BitTorrent с использованием MongoDB.
    • DebugConsole — сервер интерактивной отладочной консоли a-la telnet, который позволяет выполнять код в запущенном процессе.
    Также в поставку включены инструменты для асинхронной работы с процессами и дескрипторами (asyncProcess, asyncStream).
    Помимо этого в комплекте идут приложения-примеры.

    Будем рады вашим модулям в дистрибутиве!

    Баранов в стоило, холодильник в дом


    Лицензия — LGPL. Проект относительно свежий, в чем-то сыроватый, но стабильный, и используется в production. Разработка ведется активно. В случае отсутствия форс-мажора, фиксы выходят от нескольких минут до двух суток после репорта.

    Web: http://github.com/kakserpom/phpdaemon
    Группа: http://groups.google.com/group/phpdaemon
    IRC: irc.freenode.org #phpdaemon
    E-Mail мне лично — kak.serpom.po.yaitsam@gmail.com

    Спасибо за внимание!

    P.S. Если вам подобная архитектура импонирует — возможна поддержка, даже в принципе написание модулей на заказ.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 103

      +2
      выглядит круто
        +2
        Интересная разработка. Потестю на досуге.
          +2
          Упал. Всем спасибо.
            +1
            Класс! Но всё-таки положили, кажется :)
              0
              До. Мы это сделали!
              Брызги шампанского, визги поетесс, хлопушки и фейрверки.
              Ура, товарищи!
              0
              Чятик героически выдержал 15 человек
                0
                Да он может и 3000 =) Я тестировал на ботах.
                  0
                  Погоди, а падал он тогда зачем7
                    0
                    Он же сказал, что ребутал.
                +1
                15 человек… не густо
                  0
                  Теперь чятег будет здесь.
                    0
                    Т.е. это нечто такое, способное выполнять какие то долгие операции по команде?
                      0
                      разработка интересная, но лично мне не понравилось вот такие вот вещи {Daemon::$settings[$k] = 0;}

                      и я бы на вашем месте для создания обьектов пользовался бы fabric method — ибо public function onHandshake($client) {return $this->sessions[$client->connId] = new ChatSession($client,$this);}
                      это не дело как мне кажется.
                        –1
                        ваще не принципиально!
                        +1
                        Класс. Сам хотел сделать костыльно-ориентрированный фреймворк для демонов, но это явно перекрывает все мои нужды.
                        • UFO just landed and posted this here
                          • UFO just landed and posted this here
                              0
                              автор немножко не расчитал наверное вероломство хабраюзера и чат зафлудили/положили :)
                                0
                                Звучит прям как «Хабраюзер не прощает...»
                                  0
                                  ну не только хабраюзер. самая мелкая ошибка никогда не прощается, однако даже самое большое достижение может забываться… так устроен человек.
                              0
                              От флуда через putty на 8047 падал… или я ошибаюсь?
                                0
                                Замечательно, особенно с учетом моей любви к PHP-решениям. Обязательно потестирую на досуге.
                                  0
                                  Идеальный чатик :) Щас доков начитаюсь и буду думать чтоб сделать, уж очень вкусно все это выглядит :)
                                    +1
                                    А почему именно на Php)?
                                      +2
                                      Язык удобный. И быстрый в сравнении с другими схожими по возможностям (Ruby, Java, ASP). Ни в коем случае не хочу холи вара. Это лишь моё личное субъективное мнение :-)
                                        0
                                        Да нет мне просто интересно, сам на Php пишу. А не было желание на другом языке написать? Или по сркоам надо было быстро сделать?
                                          0
                                          90% пхпшников знают только этот язык. Это не проблема. Проблема в том, что когда им аргументированно доказывают, что их язык уступает и в возможностях, и в скорости, и в удобстве другим, то вместо того, чтобы признать узость своего кругозора и пытаться развиваться, они лишь огрызаются.

                                          Перл комментатора выше о том, что PHP быстрее Java только лишь подтверждает это.

                                          Тоже не хочу холивара, но тот факт, что сборка мусора появилась в пхп совсем недавно, ставит под сомнение попытки написания демонов на этом языке. Имхо, слишком велик риск нарваться на неожиданные проблемы. В конце-концов, у каждого языка и технологии есть свои задачи.
                                            0
                                            Хотя я и отношусь к 10% пхпшников, но для меня критическим является распространенность языка, тут уж PHP в вебе мало кому уступит (если считать по количеству инсталляций). А распространенность — это комьюнити, это готовые решения, это библиотеки/фреймворки/CMS, это хостинги, это, в конце-концов, вакансии и «лоты» на фрилансерских биржах.

                                            Те же руби и пайтон мне понравились как языки, но вот как средство зарабатывать, не владея языком в совершенстве… Just for fun :( Слишком велика ступень между «hello word» (утрирую) и редкими вакансиями Junior Python/Ruby Developer. Да и «пропихнуть» свое предложение, когда язык не задан, куда проще, если можно добавить, что скрипты будут работать на подавляющем большинстве хостингов, включая бесплатные, а не «радовать» заказчика тем, что для сайта-визитки какого-нить ООО «Рога и копыта» ему понадобится выделенный сервер.
                                    • UFO just landed and posted this here
                                        –1
                                        А почему бы не лежать dev-версии? =) Это же не production stable, и даже не бета.
                                          +1
                                          Ну был тут чатик на AMQP-сервере. Вполне себе не падал и работал шустро. Ваше решение падает. значит что-то там не так. + хотелось бы статистики, от какого наплыва людей оно упало.
                                          И почему PHP? Особенно через FastCGI. который он так и не поддерживает нормально.
                                          Может легче всеже через RabbitMQ серевер гонять сообщения, все же именно для этого Эрланг и был создан? (например)
                                        +3
                                        Выгладит, конечно, круто, но к сожалению внутри, как и прежде, такой говнокод…
                                         public function onReady()
                                         {
                                          $this->errlogfile = dirname(__FILE__).'/cgi-error.log';
                                          if (!isset(Daemon::$settings[$k = 'modcgiallowoverridebinpath'])) {Daemon::$settings[$k] = TRUE;}
                                          if (!isset(Daemon::$settings[$k = 'modcgiallowoverridecwd'])) {Daemon::$settings[$k] = TRUE;}
                                          if (!isset(Daemon::$settings[$k = 'modcgiallowoverridechroot'])) {Daemon::$settings[$k] = TRUE;}
                                          if (!isset(Daemon::$settings[$k = 'modcgiallowoverrideuser'])) {Daemon::$settings[$k] = TRUE;}
                                          if (!isset(Daemon::$settings[$k = 'modcgiallowoverridegroup'])) {Daemon::$settings[$k] = TRUE;}
                                          if (!isset(Daemon::$settings[$k = 'modcgioutputerrors'])) {Daemon::$settings[$k] = TRUE;}
                                         }
                                        • UFO just landed and posted this here
                                            +1
                                            Просто пример для подражания.

                                            Почему бы не сделать массив со значениями по умолчанию и не прибавить его к имеющемуся массиву? Это не единственный пример, там полно такого же.
                                            • UFO just landed and posted this here
                                                +3
                                                Daemon::$settings = array_merge(array(
                                                    'modcgiallowoverridebinpath'=> true,
                                                    'modcgiallowoverridecwd'=> true,
                                                    'modcgiallowoverridechroot'=> true,
                                                    'modcgiallowoverrideuser'=> true,
                                                    'modcgiallowoverridegroup'=> true,
                                                    'modcgioutputerrors'=> true,
                                                ), Daemon::$settings);

                                                (а табуляция по вкусу)
                                                  +3
                                                  читая посты TravisBickl'а, я прям разрываюсь каждый раз. с одной стороны, просто офигительнейший функционал, на который нужно потратить несколько месяцев разработки, и это очень полезный и нужный функционал, и он работает, и его можно просто так взять и скачать и даже спросить человека который его написал. с другой стороны, вот этот код вгоняет меня в ступор. xor eax,eax какой-то. и в то же время код работает, и внутренняя логика в этом коде тоже есть. но как эта логика мне чужда, её как будто писал инопланетянин. но этот инопланетянин хороший программист, судя по единому стилю написания кода и его функциональности. но каков он, этот стиль!
                                                  и так каждый раз. мучаюсь.
                                                    –3
                                                    Уважаемый коллега, Вы считаете что Ваш вариант более читабелен? Думаю, функцию array_merge знает меньше людей чем конструкцию if.
                                                    Во-вторых, мой вариант быстрее и кушает меньше памяти. При определенных условиях мой код вообще потребует записи, только проверит по порядку наличие всех переменных. Когда как Ваш в любом случае построит лишние два хеша, прогоняя проверки.

                                                    Стиль, на мой взгляд — воплощение логики. Не понимаете код — разбирайтесь, учитесь, это пойдет на пользу. Поверьте, у нас с Вами не только одна планета, но и одна страна и один город. По поводу кода — советую посмотреть вот этот кусочек кода (начиная с 1005 строки, в самом низу). Когда разберетесь и научитесь подобное писать, думаю, к Вам придет просветление и Вы сможете писать правильный код столь же легко как разговаривать. Уверяю, я этот код написал довольно быстро и читаю его как русский текст или код на любом другом языке который знаю, также легко и редактирую.
                                                      +5
                                                      «Premature optimization is the root of all evil» — Кнут. мой код может работать в два, в три или даже в пять раз медленнее, но это — инициализация приложения и это — с огромной вероятностью — не повлияет на скорость. это же будет выполняться совсем редко, ведь так?

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

                                                      я никоим образом не говорю, что код плохой. просто он непонятен. это не плохо и не хорошо. просто вы так пишете, а я этому удивляюсь.
                                                      и я совершенно согласен, что стиль — воплощение логики. я понимаю ваш код (кроме квики, да), но сквозь него нужно продираться, а читать легко и быстро не получается. возможно, дело в том, что я — посредственный программист, но ведь на это вам показал не только я, но и другие люди в этом топике. у нас у всех не получается это просто читать.
                                                      вы написали этот топик и решили поделилиться с нами, посредственными программистами, своими лучезарными регэкспами. наша ли вина в том, что регэкспы непонятны, а нативная php-реализация mysql-протокола вызывает недоумение?

                                                      и вот за то, что вы решили этим всем с нами поделиться, мы за это очень благодарны (ну, во всяком случае я. тут я без без всякого ёрничанья говорю уже)
                                                        0
                                                        Полностью согласен, в данном случае эта разница абсолютно не играет роли (т.к. вызывается 1 раз только). Более того, я старался максимально упростить процесс написания приложений. Однако, я не очень понимаю что сложного в if и isset, это первый или второй урок PHP. Может я глупый, но я не понимаю что сложного. Я ни в коем случае не утверждаю что программирую или знаю регэкспы лучше кого бы то ни было — я лишь обсуждаю и сравниваю стиль кода чтобы научиться чему-то. Ведь стиль как Вы правильно подметили един — если я осознаю возможную ошибку, весь код поменяется, это ведь вопрос продуманный, а не тяп-ляп.
                                                        Позвольте поинтересоваться, а почему достаточная понятная реализация протокола на PHP вызывает недоумение, а код mysqlnd к примеру не вызывает? И его просто используют. Он на порядок сложнее для понимания, можете убедиться. Вот я и предлагаю просто использовать мой код, не обязательно разбираться как он написан. Ничтожное малый процент программистов лезут в исходники реализации языка на котором пишут.
                                                          +2
                                                          так вот какое дело: в каждом конкретном случае ничего сложного. но из-за этих вот странных (с моей точки зрения) моментов в коде не получается прослеживать логику: «так, что тут происходит? ага, вызывается. а там что? так… а тут? а это? ой, а где мы и откуда это было вызвано?».

                                                          не обижайтесь, но такое ощущение, как будто вы много лет программировали на фортране для какой-нибудь ес эвм, потом столько же лет программировали микроконтроллеры, а потом встали не с той ноги и решили перейти на php.
                                                          ваш код очень отличается от кода всех php-проектов, которые я видел до сих пор. а на сишный код он очень-очень похож, только доллары везде расставлены. не то, чтоб это являлось проблемой само по себе, но, если вы вдруг серьёзно зададитесь целью популяризировать ваш фреймворк, то стиль кода может стать проблемой, на мой взгляд.
                                                            –1
                                                            Интересное мнение — спасибо за комментарий. Просто я до сих пор был уверен что данный фреймворк очень сильно упрощает людям жизнь. Подумаю над этим.
                                                            Думаю, язык не столь важен. Мне честно говоря всё равно на чем программировать, на PCRE многокилобайтные выражение выписывать, на PHP писать, на Java 2SE, микроконтроллеры или загрузчик ОС, или на ANSI C что-нибудь. Это всего лишь элементарные машинные языки со своими правилами, которые помогают заставить компьютер делать то что от него требуется, в рамках приемлемых ресурсов.
                                                            Чтоб понять откуда что вызвано — в PHP рулит debug_backtrace() ;-) Хотя например я и так с ходу читаю любой код на языке который знаю.
                                                            А в заключение я вам открою, на мой взгляд, справедливую мудрость. Код и есть логика, надо прослеживать логику кода, а не программиста который его писал. Код это и есть объективное выражение этой логики, остальное — фантазия. Автора кода может уже и не быть на свете, и логики никакой нигде нет, кроме той что в коде который Вы читаете. Это же не стихи, и не живопись, чтобы там сокральный смысл ловить. Это алгоритм действий, который преобразуется в весьма ограниченный набор процессорных инструкций.
                                                            Как Вы считаете, написание доки решит проблему популяризации?
                                                        +1
                                                        и, если уж говорить о скорости, то у меня такие операции:
                                                        создать массив из констант
                                                        получить массив из Daemon::$settings
                                                        смерджить эти два массива
                                                        положить результат в Daemon::$settings

                                                        а у вас:
                                                        положить в k строку
                                                        получить массив Daemon::$settings
                                                        проверить существование и ненулль элемента с индексом $k в массиве
                                                        если элемента нет, то добавить в этот массив элемент с таким индексом и значением true
                                                        положить в k другую строку
                                                        получить массив Daemon::$settings
                                                        проверить существование и ненулль элемента с индексом $k в массиве
                                                        если элемента нет, то добавить в этот массив элемент с таким индексом и значением true
                                                        и так много раз

                                                        samoval ~ # php file.php
                                                        5.8901879787445
                                                        5.1516609191895

                                                        W:\>php file.php
                                                        5.4503819942474
                                                        4.234375

                                                        (проверил два раза. на разных компьютерах)
                                                        samoval.ru/file.php.html

                                                        ВОТ ВИДИТЕ, МОЙ ВАРИАНТ БЫСТРЕЕ!!!
                                                          0
                                                          Ссылка не работает.
                                                            +1
                                                            а вы View Source нажимали?

                                                            <?
                                                            class Daemon {
                                                            	public static $settings = array();
                                                            	
                                                            	public static function reset() {
                                                            		Daemon::$settings = array(
                                                            	    'modcgiallowoverridecwd'=> false,
                                                                'modcgiallowoverridegroup'=> false,
                                                            	);
                                                            		}
                                                            	public static function asd() {
                                                            		if (!isset(Daemon::$settings[$k = 'modcgiallowoverridebinpath'])) {Daemon::$settings[$k] = TRUE;}
                                                            		if (!isset(Daemon::$settings[$k = 'modcgiallowoverridecwd'])) {Daemon::$settings[$k] = TRUE;}
                                                            		if (!isset(Daemon::$settings[$k = 'modcgiallowoverridechroot'])) {Daemon::$settings[$k] = TRUE;}
                                                            		if (!isset(Daemon::$settings[$k = 'modcgiallowoverrideuser'])) {Daemon::$settings[$k] = TRUE;}
                                                            		if (!isset(Daemon::$settings[$k = 'modcgiallowoverridegroup'])) {Daemon::$settings[$k] = TRUE;}
                                                            		if (!isset(Daemon::$settings[$k = 'modcgioutputerrors'])) {Daemon::$settings[$k] = TRUE;}
                                                            	}
                                                            	public static function qwe() {
                                                            		Daemon::$settings = array_merge(array(
                                                            		    'modcgiallowoverridebinpath'=> true,
                                                            		    'modcgiallowoverridecwd'=> true,
                                                            		    'modcgiallowoverridechroot'=> true,
                                                            		    'modcgiallowoverrideuser'=> true,
                                                            		    'modcgiallowoverridegroup'=> true,
                                                            		    'modcgioutputerrors'=> true,
                                                            		), Daemon::$settings);
                                                            	}
                                                            }
                                                            
                                                            
                                                            $ts1 = microtime(true);
                                                            for ($i=0;$i<100000;$i++) {
                                                            	Daemon::reset();
                                                            	Daemon::asd();
                                                            }
                                                            $ts2 = microtime(true);
                                                            echo ($ts2-$ts1)."\n";
                                                            
                                                            $ts1 = microtime(true);
                                                            for ($i=0;$i<100000;$i++) {
                                                            	Daemon::reset();
                                                            	Daemon::qwe();
                                                            }
                                                            $ts2 = microtime(true);
                                                            echo ($ts2-$ts1)."\n";
                                                            
                                                            
                                                            ?>
                                                              0
                                                              Вообще, изначально я говорил о языковой конструкции:
                                                              Daemon::$settings += array(
                                                              		    'modcgiallowoverridebinpath'=> true,
                                                              		    'modcgiallowoverridecwd'=> true,
                                                              		    'modcgiallowoverridechroot'=> true,
                                                              		    'modcgiallowoverrideuser'=> true,
                                                              		    'modcgiallowoverridegroup'=> true,
                                                              		    'modcgioutputerrors'=> true,
                                                              		);


                                                              Скорость варианта TravisBickle:
                                                              0.71443605423
                                                              Скорость моего:
                                                              0.367926836014
                                                                0
                                                                Остановился на Вашем варианте =) Переделаю. Благодарю.
                                                                0
                                                                у php есть замечательный баг, из-за которого очень легко подделать результаты теста (даже собственно не осознавая этого). суть его сводится к тому, что тот тет, который стоит ниже выполняется за меньшую скорость, чем тот тест, что стоит выше при прочих равных. подробнее — на форуме пхп.ру, третий пост снизу
                                                                  0
                                                                  лично у меня ваша программа даёт такие результаты: 1.1532959938049
                                                                  1.1654109954834
                                                                  я запускал её 5 раз подряд и каждый раз разница была во втором знаке. т.е. в пределах полутора процентов.

                                                                  тем не менее, я проверил свой тест, поменяв местами вызовы. ничего не изменилось.
                                                                    0
                                                                    $ time test.php
                                                            0
                                                            про xor eax,eax вы зря :)
                                                          • UFO just landed and posted this here
                                                              0
                                                              Прошу прощенья за вторжение в дискуссию, но вообще-то не затрёт ;-) Там оригинальный массив идет вторым аргументом, а не первым.
                                                              Не понял реплику про isset.
                                                                +1
                                                                мой мерге затрёт NULL'ы, если они были в настройках, но, насколько я могу судить по исходникам, это ничего не поломает.
                                                                  +1
                                                                  наоборот, то есть, не затрёт. а isset затёр бы.
                                                                +1
                                                                Или так…

                                                                $keys = array('modcgiallowoverridebinpath', 'modcgiallowoverridecwd' ,'modcgiallowoverridechroot', 'modcgiallowoverrideuser', 'modcgiallowoverridegroup', 'modcgioutputerrors');

                                                                foreach($keys as $v)
                                                                if (!isset(Daemon::$settings[$v])) { Daemon::$settings[$v] = TRUE; }

                                                                  +1
                                                                  Или так…

                                                                  $keys = array('modcgiallowoverridebinpath', 'modcgiallowoverridecwd' ,'modcgiallowoverridechroot', 'modcgiallowoverrideuser', 'modcgiallowoverridegroup', 'modcgioutputerrors');

                                                                  foreach($keys as $v)
                                                                  if (!isset(Daemon::$settings[$v])) { Daemon::$settings[$v] = TRUE; }

                                                                    +1
                                                                    Боюсь это Вы загнули… значения могут быть разные.
                                                                    • UFO just landed and posted this here
                                                                +2
                                                                да? посмеялся :)))
                                                                а что, слабо было через массив параметров сделать?
                                                                  –3
                                                                  Мы оба правы. Просто мне байтики, а вам ехать :-)
                                                                    0
                                                                    Вот оказалось не слабо — сделал!
                                                                  0
                                                                  да я думаю цепляетесь — это не говно код (пародокс в логики), а просто не переработанный код, видимо был изаначально 1 параметр, а потом стало несколько, и кто-то не сделал реконструкцию кода.
                                                                  +1
                                                                  О, асинхронный неблокирующий сервер под PHP. Надо против Node.js потестить :)
                                                                    0
                                                                    мне Ваши идеи ещё понравились во время доклада на highload-е :)
                                                                    к сожалению, применения в своих проектах пока не нашел…
                                                                      0
                                                                      Рад слышать.
                                                                      Хотя доклад, думаю, провальный получился. Опыта нет в докладах…
                                                                        0
                                                                        мы надеямся, что не последний доклад…
                                                                        доклад был не плохой, я его смотрел в онлайне, только ты очень уж разволновался и это было видно.
                                                                      +3
                                                                      >>WebSocket (!) — да-да тот самый новый протокол от Google
                                                                      Вот что значит грамотный пиар. Гугл первыми сделали реализацию вебсокетов, и теперь все думают что гугл придумал вебсокеты.
                                                                        0
                                                                        Если уж на то пошло, то первыми пропиарили, что они сделали реализацию вебмокетов ;)
                                                                          0
                                                                          *вебсокетов

                                                                        +2
                                                                        kak.serpom.po.yaitsam@gmail.com – крутой у вас email
                                                                          0
                                                                          Идёт подключение долго шло и исчезло когда я вернулся с страницы «About»
                                                                            0
                                                                            Штука очень интересная.
                                                                            Но этот код…

                                                                            Хотя, это ещё вопрос, что лучше: суровый код, вокруг которого человек не поленился написать статью, либо «правильный» код, про который думаешь «ну вот, осталось ещё чуть-чуть подпилить, тесты дописать, чтобы не стыдно было, и можно будет писать статью на Хабр»… и так уже пару лет :)
                                                                              0
                                                                              Ну я даже спорить с ними не буду… Для них лучше лишний хэш объявить чем набор условий вполне себе нормальный… т.е. код, алгоритм которого просто делает то что от него требуется, и ничего лишнего. Нет же, им надо десяток абстракций накрутить.
                                                                              0
                                                                              под оперой 10.10 не работает кнопка «Log in» и вообще не работает, и на Хабре авторизоваться не получается тоже
                                                                                –4
                                                                                Я это заметил, но честно говоря не было желания возиться с недоброузером, когда как даже в убогом IE6 всё нормально работает.
                                                                                  –1
                                                                                  Верите нет, ни под ИЕ ни под хромом тоже не работает. Send data при нажатии на Log in растет, а Recieved нет.
                                                                                0
                                                                                а какой должен быть сервер что бы выдерживать тысяч 30 таких одновременных соединений?
                                                                                  0
                                                                                  Самый обычный… дедик любой, да и VPS тоже можно подобрать.
                                                                                  +2
                                                                                  Смутило про «исключительно на пхп» и libevent. Оказалось вы все же работаете с pecl враппером, а не с libevent. Ну а проект… Не знаю, я не умею такое читать. Несколько настораживают всякое типа два подряд идущих event_base_loop. Но в любом случае для пхп мира это, конечно, прекрасная работа.
                                                                                    +4
                                                                                    > читая посты TravisBickl'а, я прям разрываюсь каждый раз. с одной стороны, просто офигительнейший
                                                                                    > функционал… с другой стороны, вот этот код вгоняет меня в ступор. xor eax,eax какой-то.
                                                                                    +1
                                                                                    Думаю, что еще наберется +100 от других людей — я слышал как минимум от троих такое же мнение.

                                                                                    ИМХО — что автору (который — для меня совершенно очевидно — весьма талантливый программист) стоит перестать упираться рогом с его неповторимым стилем кодирования и перейти-таки на PEAR/ZF Coding Standards. На это уйдет примерно неделя (у меня в начале 2000-х ушло в сумме столько), после чего карма автора резко возрастет (а заодно и email сменить бы еще :).
                                                                                      –3
                                                                                      Знаете, Дмитрий, а когда я читал Ваш код (JsHttpRequest) и исходники «правильного» чата chat.php.spb.ru, у меня он не вызвал ничего кроме отвращения :-) Но это не из-за стиля (хотя он мне тоже не понравился), а из объективных показателей, таких как переносимость, совместимость, производительность, расширяемость.
                                                                                      Исходники PEAR того хуже, одних собак в коде хватит на целый питомник.

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

                                                                                      Никого обидеть не хочу, у нас у всех ДНК очень похожее.
                                                                                        +4
                                                                                        Э-эээ…

                                                                                        dklab.ru/lib/JsHttpRequest/demo/lib/JsHttpRequest/JsHttpRequest.js — это файл после DOJO-минимизации (если Вы его смотрели).

                                                                                        А chat.php.spb.ru — это не мой, а Дмитрия Бородина, Вы перепутали. :-)

                                                                                        В общем, мы Вам тут сигнализируем о проблеме и от чистого сердца советуем придерживаться задокументированных стандартов кодирования, которыми пользуются тысячи человек. А Вы уж сами решайте. Поставьте «плюс» все, кто думает так же. :-)
                                                                                          –2
                                                                                          Мне это напоминает, Вы уж извините, отеческое напутствие коммунистических бонз в сторону Битлов. Я даже близко не понимаю для чего Вам изменения стиля кодирования серпояйцего (не знаю настоящего имени). И уж, тем более, я не знаю для чего это имяреку.

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

                                                                                          P.S. Меня не покидает ощущение, что отторжение кода имярека у сообщества произошло из-за его подчёркнутой самоуверенности. Да, меня тоже это бесит, но при чём тут код?
                                                                                            +1
                                                                                            Спасибо за комментарий. Мне это может быть нужно для популяризации. Ведь я перестаю быть малолетним гиком который пишет код ради кода. Код сам по себе мало чего стоит, если его не используют люди. Кстати я поправил этот кусок кода везде. Теперь плюсуется массив.

                                                                                            Правильный у Вас взгляд. Но мир не переделаешь, большинство хочет либо просто либо никак. А почему уверенные в себе люди Вас бесят? Это же хорошо. Если человек действительно знает всё дело, он уверен в себе и в своих силах… Я ведь никого этим не хочу задеть, это личное дело каждого как он относится к себе лично =)
                                                                                              0
                                                                                              Ну, значит я не прав и не дорос до Вас. :) На мой взгляд код — выражение идеи. Сам по себе он ничего не даёт, главное — технологии, алгоритм, идея. Если его можно поддерживать и развивать при том стиле написания который есть — зачем менять стиль? При этом я понимаю, что мои рассуждения абсолютно не применимы для Open Source. Но, как я сказал выше, я для вклада в OS не дорос.
                                                                                              Меня бесит то, что Вы подчёркнуто самоуверенны. То, как Вы иногда строите фразы, вызывает у меня ощущение самолюбования. Вот именно оно и бесит.
                                                                                              Ваша уверенность в своих силах и знаниях, на мой взгляд, объективна, и она даже близко не вызывает отторжения :)
                                                                                                0
                                                                                                Пять баллов. :)

                                                                                                Главное иногда не зарываться и уметь перешагивать через свои ошибки :)
                                                                                              0
                                                                                              Прошу прощенья, мне давали ссылку на тот чат, говоря именно Ваше имя, говоря про JsHttpRequest и т.д. Ошибочка вышла :-)

                                                                                              Спасибо за совет, Дмитрий, я постараюсь, правда. Извините еще раз за ошибку.
                                                                                              –1
                                                                                              Лучше уж так как в исходниках чата чем 100500 велосипедов в коде :)
                                                                                              0
                                                                                              P.S. Тон комментария получился не совсем удачный, если что прошу извинить. Наезжать не хотел, это просто беседа «о птичках».
                                                                                                0
                                                                                                Дмитрий,

                                                                                                про чистоту кода ему раз сто
                                                                                                говорили, когда он тусовался на PHPClub…

                                                                                                но, что ни говорите, а голова у него на плечах…
                                                                                                0
                                                                                                Василий,

                                                                                                молодец, осваиваешь NoSQL
                                                                                                и комментарии мне твои понравились…

                                                                                                желаю успехов!
                                                                                                  0
                                                                                                  народ, может кто независимое сравнение сделает php-fpm — phpDaemon?
                                                                                                    0
                                                                                                    и выложит статью на Хабре
                                                                                                      +1
                                                                                                      Зачем их сравнивать? У ФПМ — скорострельные одноразовые странички, у пхпдемона — приложения висящие в памяти. Делать на демоне одноразовые страницы неверно. Делать на фпм приложения в памяти не получится.
                                                                                                      0
                                                                                                      soullink.habrahabr.ru/blog/82140/ Инструкция по установке
                                                                                                        0
                                                                                                        А что для этого нужно? Такой демон на PHP можно на обычный shared-хостинг засабачить?
                                                                                                          0
                                                                                                          В целом здорово, но как-то сумбурно код написан… И надо уточнять что он сразу заточне только для php 5.3, как я понял, ниже версии использовать нельзя.
                                                                                                            0
                                                                                                            А в чем сумбурность? По-моему замечательный код.
                                                                                                            0
                                                                                                            Тут в Q&A вопрос подняли habrahabr.ru/qa/973/#answer_4115 — как c утечками памяти в php вообще? А мне интересно как с ними в вашем демоне. Рестартовать периодически рекомендуете или месяцами без проблем может работать?
                                                                                                              0
                                                                                                              Утечки безусловно есть, но воркеры сами плавно перезапускаются при достижении заданного порога памяти, так что это не проблема и работает месяцами стабильно.
                                                                                                              0
                                                                                                              Вопрос: а почему не Gearman, скажем, в качестве асинхронного фреймворка? Там, ведь, тоже можно в воркере поднять коннект и другие персистентные объекты до ухода в цикл обработки сообщений.
                                                                                                                0
                                                                                                                Скажите а что с поддержкой Oracle

                                                                                                                Only users with full accounts can post comments. Log in, please.