[Из песочницы] Phalcon Framework на продакшене
Последним временем известность набирает необычный в среде php фреймворк Phalcon, который является расширением языка. Думаю, что многим интересно узнать, каков фреймворк в бою, однако по тем или иным причинам не могут позволить себе использовать его в разработке. В моей компании решились на такую авантюру и я спешу поделиться увиденным и нащупанным. Добро пожаловать под кат.Откуда ноги растутВ компании есть проект, для которого требуется диспетчер. Грубо говоря, это механизм проксирования и балансировки виджетов в зависимости от предпочтения пользователя. Текущий диспетчер достался в наследство толи от инков, толи ацтеков, что породило внутри коллектива убеждения, что диспетчер был всегда и без него будет тоже, что с Землёй без календаря Майя. Иными же словами, код страшен, запутан, но работает и требует поддержки. Написан диспетчер на Zend Framework 1, расположен код на нодах Amazon, а именно на c3.xlarge, используется APC. При пиковых нагрузках доходит до 8–10 тысяч хитов в минуту и в такие моменты работают 5 нод. Меня это положение вещей совсем не устраивало, так как сам диспетчер не содержит в себе сложного функционала, работа с БД на примитивном уровне, результаты которой кешируются, да и все, что можно — сложено в кеш. Основная нагрузка — это php и Zend. От php отказаться не получится, а вот со вторым вариантом можно попробовать, тем более что для диспетчера мощности и гибкости фреймворка совершенно не требовалось, а на первом месте в приоритете стояла скорость работы и потребление ресурсов.За ходом разработки Phalcon я следил давно, потому что его benchmark, еще, и и еще мне очень нравились и хотелось попробовать его в чем-то нагруженном. Что ж, настал его черёд и я на скорую руку, переписав критично важный код диспетчера на Phalcon, решил погонять его на тестовой ноде (m3.medium) с APC. Для тестирования я использовал jmeter, создал простые нагрузочные тесты и запустил их в 500 потоков.
Нагрузочное тестирование показало, что расход памяти уменьшился в два раза, по сравнению с Zend. Мерял каждый запрос с помощью memory_get_usage ().
Так как тогда я не думал, что я буду писать статью, потому не сделал скриншоты консоли и графиков амазона. Приведу сравнение в таблице:
Framework Threads Loop Hits Max load average Test runtime Average response, ms Median, ms Min, ms Error Zend 500 60 30000 125 03:30:00 3,083 2,028 271 2.83% Phalcon 500 60 30000 76 01:55:00 1,549 947 138 0.86% Релиз Результаты порадовали и было решено переносить проект на Phalcon. После небольшого рефакторинга кода, внедрения DI контейнера код был протестирован и готов к продакшену.Хочу подчеркнуть, что код не был значительно оптимизирован, во многих местах код получил только косметический рефакторинг. Когда настал час «Ч» с замиранием сердца выкатил на ноды код и стал мониторить за состоянием системы. Вот какой график получился:
Что мы видим: релиз был в пиковое время по нагрузке — работало 5 нод на Zend, c нагрузкой по CPU под 80%. После обновления 5 нод на Phalcon, нагрузка упала ниже 20%. На графике видно, что есть возврат к 5 нодам Zend — это было сделано для того, чтобы убедиться, что все графики мониторинга Zend совпадают с Phalcon. Все было хорошо, потому решил отключить три ноды и посмотреть, как будет справляться Phalcon. Две ноды использовали чуть более 45% CPU, что позволило попробовать авантюру и оставить одну ноду. CPU упёрлось в 100% и пошли 500-е ошибки, однако проблема была не с Phalcon, а с Nginx, которому стало тяжело держать большое количество соединений. Сразу же вернул в балансировщик одну ноду, и поставил себе задачу на будущее подкрутить Nginx. Замена Zend на Phalcon позволила перейти с 5 нод на 2 ноды, что снизило расходы на Amazon, а также облегчило деплой и мониторинг системы.
Несколько слов о самом фреймворке Не буду описывать сам фреймворк, так как документация на сайте хорошая, есть на русском и цель статьи другая.На момент рефакторинга, актуальная версия фреймворка была 1.2.6, которая и использовалась. Фреймворк нисколько не показался сырым — никаких багов с функционалом, который нам требовался замечено не было. Также замечу, что Phalcon умеет достаточно много чего и работало все в соответствии с документацией.
Использовал работу с моделями со встроенным Active Record. Модели мощные, умеют много чего — валидация, кеширование, связи, виртуальные внешние ключи и так далее. Для изощренных запросов есть свой мета-язык PHQL. Для заинтересовавшихся — ссылка на документацию.
Во время разработки были проблемы с кешом — в какой-то момент я заметил, что очень странно кешируются данные, соединение с memcache происходит более одного раза, не всегда кеш есть, хотя в memcache данные попадают. Проблема оказалась в том, что я не верно использовал DI container. Я кеш добавлял через метод set (), и при обращении к DI контейнеру каждый раз получал новый экземпляр класса, с новым соединением к мемкешу.А для того, чтобы возвращался каждый раз один и тот же объект, нужно класть его в контейнер вот так:$di→setShared ('cache', $cacheObject); Исправив ошибку, все заработало как ожидалось. Данный подход позволил отказаться от всех Singleton в проекте, что и было с удовольствием сделано.
После релиза, вышла в свет следующая версия фреймворка — 1.3, которая без проблем установилась и работала с кодом проекта. Пришлось подправить только пару мест с DI контейнером, чтобы завести приложение.
Работа с CLI Работа с консольными тасками в Phalcon совсем простая и пока что не имеет больших возможностей, по сравнению, например с Zend. Нет возможности указать параметры по умолчанию, а обязательные — попросить дописать при вызове таска прямо в консоли. Работа с параметрами сводиться к самостоятельному парсингу $argv; Также нет никаких красивостей с цветными текстами, фонами, так что разукрасить консоль радугой не получится. Но с другой стороны, хоть функционал не богат, но все же свою функцию исполнят. А со временем появятся примочки и свистелки.Немного дёгтя Расстроило отсутствие в фреймворке элементарного LogNull для логирования, который пришлось дописать на php.Также удивило отсутствие возможности мерджить конфиги.Из недостатков, которые могут быть для кого-то серьёзным аргументом отказаться — это невозможность поправить код фреймворка. Если вы обнаружите уязвимость, то ничего не сможете с этим сделать — исходники скомпилированы. Однако разработчики переписывают Phalcon на Zephir (подробнее о Zephir попытаюсь написать отдельную статью), что даст возможность править сам фреймворк, а также писать для него расширения на C.
Это будет сделано в версии Phalcon 2.0, которая на сегодня имеет состояние Beta 1. Надеюсь, что в скором времени мы увидим стабильный релиз.
Есть что ещё рассказать о фреймворке, однако думаю, что это тема для отдельной статьи, потому подведу вкратце итог использования на нагруженном проекте Phalcon: — производительность не сравнимая с Zend (аналогичными php фреймворками)— прост в изучении, если есть опыт работы с фреймворками— фреймворк не выглядит сырым и недоделаным, однако есть куда расти и развиваться— невозможно поправить код фреймворка