Проблема родителей и детей существовала всегда и не только в семье Apache prefork MPM работающего как backend под frontend-ом Nginx, а и в обычных традиционных человеческих семьях, где бесконтрольно расплодившиеся child-ы (дети) пожирали одним махом всё шо было нажито непосильным трудом!:)
Например мы, Apache prefork MPM, живём вчетвером (httpd) на десяти сотках земли (мегабайтах памяти) и нам этого вполне хватает для нормальной жизни на протяжении 365-и дней в году, обычно рождая одного child-а (потомка) раз в 10-30 лет (сек.) и отпевая за этот же период по одному потомку (httpd). Такая схема жизни позволяет жить тихо мирно и без скандала, поддерживать связь с окружающим миром, frontend-ом Nginx, находить время для отдыха и творчества.
Но вдруг мы всей семьёй Apache prefork MPM сходим с ума и начинаем бесконтрольно плодить child-ов (детей httpd) так, как будто мы живём не на десяти сотках (мегабайтах памяти) земли, а на 10-ти гектарах (гигабайтах памяти), а у тех child-ов в свою очередь тоже съезжает чердак и они начинают плодится без остановки. Семья Apache prefork MPM живущая как backend под frontend-ом Nginx начинает голодать обслуживая своих многочисленно порождённых child-ов, которые заполонив отведённые нам 10-ть соток стали брать кредиты в банках под большие проценты, искать свободные территории (ушли в Swap) и воевать с соседями (сервисами) за ресурсы (память, ЦП и т.д.).
В итоге сошедшая с ума семья Apache prefork MPM со своими расплодившимися child-ами стала очень редко и туго контачить с окружающим frontend-ом Nginx, перестала отдыхать и заниматься творчеством - настал типа кризис:) Для того чтобы поправить ситуацию в семье Apache prefork MPM, нам нужно либо реже плодить child-ов, дожидаясь пока позаворачиваются уже наделанные или убивать их раньше времени сократив их срок жизни.:)
Ну, третьего тут не дано - или в семье Apache prefork MPM не плодить child-ов сверх необходимого или же убивать их раньше времени, а в некоторых случаях будет полезно и то и другое! Госпади, какие кошмарные планы, убивать child-ов это же не гуманно!;)) Гуманно или не гуманно, а всё равно места на всех child-ов Apache prefork MPM не хватит!
Итак, да прасти нас Госпади, приступим к осуществлению геноцида child-ов рода Apache prefork MPM:) После рестарта/перезапуска веб сервера Apache запускаем утилиту topи смотрим в Mem: ... 105129k free, ..., т.е. после рестарта/перезапуска веб сервера Apache у нас было больше 100 МВ (105129k) свободного оперативного мозга/памяти, а через 10-30 мин. работы, веб сервер Apache с настройками по умолчанию, снова вместе со своими расплодившимися child-ами (детьми) съел всю раму (RAM) надолго и не подавился. В результате получили вечное Mem: ... 4083k free, ..., а всё остальное уйдёт в Swap брать кредиты под большие проценты!:)
Потому как Apache prefork MPM работает у нас как backend под frontend-ом Nginx-а, то KeepAlive Off, Timeout 10 вместо 60-ти, а также пониженные значения параметров Apache prefork MPM, в скобках указаны значения по умолчанию:
Timeout 10 KeepAlive Off KeepAliveTimeout 2 # prefork MPM # StartServers: number of server processes to start (8) # MinSpareServers: minimum number of server processes which are kept spare (5) # MaxSpareServers: maximum number of server processes which are kept spare (20) # ServerLimit: maximum value for MaxClients for the lifetime of the server (256) # MaxClients: maximum number of server processes allowed to start (256) # MaxRequestsPerChild: maximum number of requests a server process serves (4000) <IfModule prefork.c> # количество детей создаваемых при запуске Apache StartServers 3 # минимальное число неиспользуемых (ждущих) дочерних процессов сервера MinSpareServers 3 # максимальное число неиспользуемых (ждущих) дочерних процессов сервера MaxSpareServers 7 # максимальное количество одновременных соединений ServerLimit 64 MaxClients 64 # child-ы после обработки 300-т запросов к нему масцдай MaxRequestsPerChild 300 </IfModule>
- StartServers - количество детей создаваемых при запуске Apache
- MinSpareServers - минимальное число неиспользуемых (ждущих) дочерних процессов сервера
- MaxSpareServers - максимальное число неиспользуемых (ждущих) дочерних процессов сервера
- ServerLimit (MaxClients) - максимальное количество одновременных соединений
- MaxRequestsPerChild - child-ы, после обработки этого количества запросов к ним, масцдай
Если мозг продолжает утекать, то можно попробовать понизить MaxRequestsPerChild до 100-150 или испробовать такую комбинацию:
Timeout 5 KeepAlive Off KeepAliveTimeout 2 # prefork MPM # StartServers: number of server processes to start (8) # MinSpareServers: minimum number of server processes which are kept spare (5) # MaxSpareServers: maximum number of server processes which are kept spare (20) # ServerLimit: maximum value for MaxClients for the lifetime of the server (256) # MaxClients: maximum number of server processes allowed to start (256) # MaxRequestsPerChild: maximum number of requests a server process serves (4000) <IfModule prefork.c> StartServers 3 MinSpareServers 3 MaxSpareServers 4 ServerLimit 24 MaxClients 24 MaxRequestsPerChild 250 </IfModule>
Теперь после перезапуска/рестарта Apache service httpd restartкругооборот child-ов рода Apache prefork MPM работающего как backend под frontend-ом Nginx существенно стабилизировался и пожираемая ими память составляет в пределах 20-90 МВ, оставляя нам в Mem: ... 10388k free, ..., с частым регулярным освобождением памяти до Mem: ... 55278k free, ..., и выше до 80 МВ.
При таких настройках Apache prefork MPM работающего как backend под frontend-ом Nginx, Mem: ... 10388k-18238k free держится стабильно даже при одновременном натиске Googlebot/2.1 и других пользователей, а когда сайтеги сервера перестают непрерывно юзатся то памяти освобождается до 80 МВ!
Так у нас теперь в семье Apache prefork MPM установился нормальный баланс чилдов, нахлобучивание которых ограничено параметрами MaxSpareServers, ServerLimit и MaxClients, а MaxRequestsPerChild заставляет child-ов самоубиваться после обработки 300-т запросов.
Значение параметра MaxRequestsPerChild можно установить с запасом, в два три раза превышающее значение поля Requests (количество запросов для загрузки страницы) в результатах анализа скорости загрузки сайта, хотя тут ещё играют роль значения директив MaxSpareServers, ServerLimit и MaxClients и чем меньше (child-ов) их значение, то тем больше можно увеличить (время их жизни) значение для MaxRequestsPerChild.
Такая конфигурация Apache prefork MPM работающего как backend под frontend-ом Nginx хорошо подходит для серверов с размером оперативной памяти в 256 МВ, где 120-140 уходит под работу системы, а 100-110 остаётся в свободном распоряжении.
Недостатки Apache prefork MPM backend под frontend-ом Nginx
Одним из пока найденных недостатков является невозможность правильного определения CMS-ами внешнего ИП пришедшего пользователя, который будет определятся как 127.0.0.1/localhost, адрес frontend-а Nginx берущего контент с backend Apache prefork MPM!
В этом можно убедится посетив главную страницу нашего сайта, смотреть внизу страницы на "Внешний IP" и "Прокси сервер", где в "Прокси сервер" будет указан ваш реальный ИП но, увы, теряется возможность определения наличия реального прокси сервера, который возможно будет использовать посетитель!
Решается установкой mod_rpaf на Apache (reverse proxy add forward module for Apache) или mod_realip2 (mod_realip для Apache 1.3). Устанавливаем mod_rpaf:
wget http://centos.alt.ru/repository/centos/6/i386/centalt-release-6-1.noarch.rpm rpm -Uvh centalt-release*rpm yum install mod_rpaf
Модули у нас валяются в /etc/httpd/modules -> /usr/lib64/httpd/modules, дополнительные конфиги в httpd.confгрузятся директивойInclude conf.d/*.confиз /etc/httpd/conf.d, делаем конфиг для mod_rpaf:
vi /etc/httpd/conf.d/mod_rpaf.conf LoadModule rpaf_module modules/mod_rpaf-2.0.so RPAFenable On RPAFsethostname On RPAFproxy_ips 127.0.0.1 RPAFheader X-Forwarded-For service httpd restart
ВНИМАНИЕ! В mod_rpaf.conf директиву RPAFsethostname On лучше закомментировать иначе при работе с формами авторизации и пр. может косячить на внешний IP зашедшего пользователя!
Проблемы: mod_rpaf не работает
Для правильной работы модуля mod_rpaf под Apache в связке с Nginx, веб сервер Nginx должен быть скомпилирован с поддержкой модуля ngx_http_realip_module, поддержка которого обеспечивается с помощью конфигурационного параметра --with-http_realip_module, который согласно официальной документации по умолчанию опускается (не собирается) во время компиляции Nginx но, в тоже время, обычно сборки Nginx доступные в большинстве репозиториев скомпилированы с конфигурационным параметром --with-http_realip_module. Проверить скопмилирован ли ваш Nginx с конфигурационным параметром --with-http_realip_module можно выполнив nginx -V - если в результатах присутствует --with-http_realip_module, то значит с ngx_http_realip_module всё ОК.
Мало того, недостаточно одного наличия скомпилированных и подключённых модулей ngx_http_realip_module и mod_rpaf, для передачи реального IP с Nginx в Apache нужно правильно настроить, передать и принять HTTP заголовки:
[root@localhost ~]# vi /etc/httpd/conf.d/mod_rpaf.conf ..... RPAFheader X-Real-IP RPAFheader X-Forwarded-For [root@localhost ~]# service httpd restart [root@localhost ~]# vi /etc/nginx/nginx.conf server { location / { ..... proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $http_x_forwarded_for; } } [root@localhost ~]# service nginx restart
Пробремы с mod_rpaf после обновления до mod_rpaf-0.8-3.el6.art.x86_64.rpm
После обновления mod_rpaf-0.6-2.el6.art.x86_64.rpm до mod_rpaf-0.8-3.el6.art.x86_64.rpm, при старте Apache выдает такие ошибки:
[root@localhost ~]# httpd -t
Syntax error on line 222 of /etc/httpd/conf/httpd.conf: Syntax error on l
ine 2 of /etc/httpd/conf.d/mod_rpaf.conf: Cannot load /etc/httpd/modules/mod_rpa
f-2.0.so into server: /etc/httpd/modules/mod_rpaf-2.0.so: cannot open shared obj
ect file: No such file or directory
[root@localhost ~]# httpd -t
Syntax error on line 4 of /etc/httpd/conf.d/mod_rpaf.conf:
Invalid command 'RPAFenable', perhaps misspelled or defined by a module not incl
uded in the server configuration
А в браузер получаем HTTP 502 Ошибка межсетевого шлюза.
В mod_rpaf-0.6-2.el6.art.x86_64.rpm модуль назывался mod_rpaf-2.0.so, а в версии mod_rpaf-0.8-3.el6.art.x86_64.rpm модуль переименовался в mod_rpaf.so, более того изменились имена директив в конфиг файле /etc/httpd/conf.d/mod_rpaf.conf! Теперь вместо RPAFheader используется RPAF_header, тобишь после каждого RPAF ставится знак подчёркивания!
Порядок действий для устранения ошибок:
yum remove mod_rpaf rm /etc/httpd/conf.d/mod_rpaf.conf.rpmnew rm /etc/httpd/conf.d/mod_rpaf.conf.rpmsave yum install mod_rpaf vi /etc/httpd/conf.d/mod_rpaf.conf LoadModule rpaf_module modules/mod_rpaf.so <IfModule mod_rpaf.c> RPAF_Enable On RPAF_ProxyIPs 127.0.0.1 RPAF_Header X-Forwarded-For RPAF_header X-Real-IP #RPAF_SetHostName On #RPAF_SetHTTPS On #RPAF_SetPort On </IfModule>
Эпилог
На примере детей семейства Apache prefork MPM работающих как backend под frontend-ом Nginx, можно убедится в том, как важно сохранять баланс между сущностями и не плодить их сверх необходимого мхо еже чревато это затяжным кризисом и межусобными войнами.
Главный СисьАдмин человечества видимо где-то загулял или запил и не заметил даже, что конфигурация сервера по имени Земля не выдерживает никакой критики, а подправить то ServerLimit, MaxClients и MaxRequestsPerChild некому или же Он всё правильно настроил, да в процессе что-то глюкануло, хакеры ломанули, а пропатчить то некому, ведь Главный СисьАдмин в загуле - жаль у меня нет доступа к конфигурационным файлам человечества!...
P.S. Дайте мне исходники вселенной и хороший дебагер!