Nginx Unit и PHP

September 05, 2019 SOFTWARE NGINX

Во время очередной сессии обновления систем, мне пришла в голову идея - почему бы не оставить в стороне php-fpm и не запустить свои приложения на php за каким-нибудь сервером приложений. Что у нас есть на выбор из более-менее производительных и в то же время эффективных по памяти вариантов? Вобщем-то немного. Сам php-fpm, uWSGI, nginx unit. вот собственно и весь список.

загуглив вопрос производительности, я узнал, что uwsgi с некоторого времени заметно прокачался и с версии 2.0.12 (2015-й год) более-менее неплохо себя ведёт. Nginx Unit - довольно специфичный сервер приложений и тоже ведёт себя неплохо. Во многих тестах uwsgi и unit оказывались постабильнее в работе, чем php-fpm. Ну, то есть если их задавить запросами, то они начинают деградировать по времени, но более-менее консистентно. В отличие от них разброс по времени ответа у php-fpm с нагрузкой растёт значительно и при относительно большой нагрузке fpm начинает таймаутить. Это какбэ не айс.

Убедил себя попробовать. Благо, что unit, что uwsgi вобщем-то несложно запустить и посмотреть как оно себя ведёт. На стороне nginx-а надо настроить http_pass в очередной сервер приложений.

Берём alpine linux и оказывается, что uwsgi там бракованный - есть поддержка только для питоновых приложений. Такого подвоха я не ожидал. Роскошный сервер приложений так изуродовать надо постараться. Запишем этот минус в карму мэйнтэйнеров alpine linux.

Остаётся nginx unit. Ну, что же - давайте возьмём его за рога и настроим поработать. вся настройка сводится к генерации json-а и скармливанию его в control socker сервера приложений. Далее он сам поднимает listener на нужных ip:port и настраивает пул приложений.

На самом деле, под капотом у него не человекочитаемый json в каталоге /var/lib/unit/conf.json. То есть можно писать в него и рестартовать unit.

Примерно такой конфиг достаточно затолкать в unit, чтобы он поднял на 8380 сервер приложений:

{
    "applications": {
        "my_app": {
            "type": "php",
            "processes": {
                "max": 5,
                "spare": 2
            },
            "user": "www",
            "group": "www",
            "root": "webroot_dir",
            "index": "index.php"
        }   
    },
    "listeners": {
        "127.0.0.1:8380": {
            "application": "my_app"
        }
    }
}

Запихивается конфиг в запущенный сервер приложений вот так:

curl -X PUT --data-binary @config.json --unix-socket /run/control.unit.sock http://localhost/config

Есть важный момент. Рекомендуется прятать unit за frontend и не выставлять наружу неприкрытым.

На самом деле сам по себе сервер приложений рассчитан больше на администраторов, а не на разработчиков. То есть конфигурировать и обслуживать его довольно просто. Расширенных настроек в нём пока очень мало. Другое дело uwsgi...

После установки unit в качестве сервера приложений время отклика от web-приложений изменилось примерно также как после перехода с apache+mod_php на nginx+php-fpm. То есть джиттер в ответах сократился, что сказалось положительным образом на ajax-запросах, точнее на ответы на них (то есть с tt-rss, например, стало удобнее работать).

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

Подводя итоги вышесказанному - уход от php-fpm в сторону unit или uwsgi вполне оправдан, также оправдан, как переход от apache+mod_php в сторону nginx+сервер приложений.

Next Post