Масштабирование Nginx, PHP-FPM и MongoDB

#php #linux #mongodb #nginx

#php #linux #mongodb #nginx

Вопрос:

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

Все происходит быстро, пока он не находится под большой нагрузкой. Время отклика сокращается где-то от 2 до 50 секунд. При небольшой загрузке время отклика варьируется от 100 до 300 миллисекунд.

Настройка сервера — это 2 сервера. Балансировщик нагрузки впереди, PHP-FPM, Nginx и MongoDB на обоих блоках. Один сервер запускает mongod master и arbiter, другой запускает slave (если не происходит переключение). Я знаю лучшие практики работы с Mongo, но у меня недостаточно серверов, чтобы иметь выделенные серверы баз данных.

Все еще остается довольно много свободной оперативной памяти, а средняя загрузка за последнюю 1 минуту никогда не превышает 0,7. Это 8 блоков ядра с 16 гигабайтами оперативной памяти каждый, так что это не должно быть узким местом. Mongo вообще не потеет, и Nginx и PHP-FPM, похоже, тоже. Я проверил top statistics и MongoDB с помощью db.serverStatus().

Мой вопрос в том, учитывая мой параллелизм, выглядят ли мои настройки Nginx fastcgi правильно, и есть ли что-то еще, чего мне может не хватать, даже если это не имеет никакого отношения к настройкам Nginx?

 fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
  

Замедлит ли это низкий «ulimit -n»? Mongo использует от 500 до 600 соединений при большой нагрузке. Настройки Ulimit следующие:

 core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 147456
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 147456
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
  

К вашему сведению, я буду повышать «ulimit -n» при нагрузочном тестировании на 1200 параллелизмов.

Заранее спасибо.

Ответ №1:

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

nginx.conf

 worker_processes 4;
events {
    worker_connections 1024;
}
  

И 16 ГБ оперативной памяти дадут некоторое пространство для постоянного количества работников php-fpm.

php-fpm.conf

 pm = static
pm.max_children = 4096
  

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

Кажется, что один сервер обрабатывает около 2000 параллелизмов, прежде чем нагрузка становится довольно высокой. ApacheBench начинает получать ошибки при параллелизме 500, поэтому тестирование с помощью AB должно выполняться с нескольких серверов.

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

Я надеюсь, что это поможет другим.

Комментарии:

1. Вы не думаете, что вам следует увеличить лимит открытых файлов? Также 4096 дочерних элементов php-fpm для 16 ГБ оперативной памяти слишком высоки. Вы должны проверить статус php-fpm на его странице статуса.

Ответ №2:

MongoDB здесь не является узким местом. Если вам нужно более 1200 одновременных подключений, PHP-FPM (и PHP в целом) может не подойти для этой работы. На самом деле, вычеркните это. Это НЕ подходящий инструмент для этой работы. Многие тесты утверждают, что после 200-500 одновременных подключений nginx / PHP-FPM начинает давать сбои (смотрите здесь).

Я был в аналогичной ситуации в прошлом году, и вместо того, чтобы пытаться масштабировать немасштабируемое, я переписал приложение на Java, используя Kilim (проект, в который я также внес свой вклад). Еще один отличный выбор — написать его на Erlang (который Facebook использует). Я настоятельно рекомендую вам пересмотреть свой выбор языка здесь и провести рефакторинг, пока не стало слишком поздно.

Предположим, вы получаете PHP-FPM, работающий «нормально» с 1200, возможно, даже 1500 одновременными подключениями. Что насчет 2000? 5000? 10000? Абсолютно, однозначно, бесспорно невозможно.

Комментарии:

1. К сожалению, на данный момент это не вариант. Это не работает под управлением CakePHP или Zend Framework и не является чем-то вроде WordPress — это простой сервис JSON, поэтому масштабирование его для достижения моей цели должно быть достижимым.

2. Я должен добавить, однако, что на более позднем этапе рефакторинг с использованием другого языка, такого как Erlang, определенно является вариантом.

3. Я думаю, StackOverflow должен заставить пользователя объяснить, почему он голосует против кого-то.

4. Если у вас есть только 1 сервис, вы можете рассмотреть возможность использования сервера GWAN и написать небольшой файл на C или скомпилировать его с помощью HipHop! Кроме того, почему вы не используете поисковую систему, такую как Solr или ElasticSearch? Mongo может быть медленным для запросов агрегации

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