Назад | Перейти на главную страницу

Как исследовать утечку памяти с помощью Apache и PHP?

У нас есть мощный сайт на Drupal, который выполняет финансовое моделирование. Похоже, что мы сталкиваемся с какой-то утечкой памяти, учитывая тот факт, что со временем объем памяти, используемый apache, увеличивается, в то время как количество процессов apache остается стабильным:

Мы знаем, что проблема с памятью исходит от apache / PHP, потому что всякий раз, когда мы выдаем /etc/init.d/httpd reload использование памяти падает (см. снимок экрана выше и ниже выходы интерфейса командной строки):

Перед перезагрузкой httpd

$ free
             total       used       free     shared    buffers     cached
Mem:      49447692   45926468    3521224          0     191100   22609728
-/+ buffers/cache:   23125640   26322052
Swap:      2097144     536552    1560592

После перезагрузки httpd

$ free
             total       used       free     shared    buffers     cached
Mem:      49447692   28905752   20541940          0     191360   22598428
-/+ buffers/cache:    6115964   43331728
Swap:      2097144     536552    1560592

Каждому потоку apache назначается PHP memory_limit 512 МБ, что объясняет высокое использование памяти при низком объеме запросов, и max_execution_time 120 секунд, что должно завершать потоки, выполнение которых занимает больше времени, и, следовательно, должно предотвращать постоянный рост использования памяти, который мы наблюдаем.

В: Как мы можем выяснить, что вызывает эту утечку памяти?

В идеале я ищу шаги по устранению неполадок, которые я могу выполнить в системе, не беспокоя команду разработчиков.

Дополнительная информация:

OS: RHEL 5.6
PHP: 5.3
Drupal: 6.x
MySQL: 5.6

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

Мы знаем, что проблема с памятью исходит от apache / PHP, потому что всякий раз, когда мы запускаем /etc/init.d/httpd перезагрузку, использование памяти падает.

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

Каждому потоку apache назначается PHP memory_limit 512 МБ, что объясняет

Нет, это не так. Вы сообщаете в среднем о 7 и максимум о 25 загруженных серверах, но график вашей памяти показывает дельту около 25 ГБ.

На самом деле вам следует начать снова с базовой настройки HTTP - похоже, вы используете постоянный 256 httpds, но ваше пиковое использование составляет 25 - это просто глупо.

и max_execution_time в 120 секунд, который должен завершать потоки, выполнение которых занимает больше времени

Нет - только если поток выполнения находится в интерпретаторе PHP - не если PHP заблокирован.

который выполняет финансовое моделирование

(вздох)

Было бы полезно, если бы вы предоставили подробную информацию о том, как вы настроили Apache, многопоточную или предварительную версию, какую версию, как вызывается PHP (модуль, cgi, fastcgi), используете ли вы постоянные соединения, используете ли вы хранимые процедуры.

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

Вы, наверное, уже решили свою проблему. В качестве промежутка времени, чтобы сервер не менял местами / сбивал, я каждый час запускаю следующую команду из cron:

#!/bin/sh 
sync; echo 3 > /proc/sys/vm/drop_caches

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

Более подробную информацию можно найти здесь.

http://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/

По-видимому, именно так работает PHP - и если вы выполняете длинные циклы, в которых вы выделяете объекты и кто знает, передаете ли вы их также через ссылку, поэтому единственный способ справиться с этим - это после N запросов для каждого процесса PHP чтобы остановить это. Если вы запускаете PHP как CGI, каждый запрос вызывает его возрождение - поэтому утечки памяти нет, и падение производительности может быть не таким большим. Вы также можете запустить fast-cgi, где, например, каждые 1000 запросов процесс php-fcgi завершается, и его память высвобождается - снова нет утечки памяти. Если вы запускаете PHP как модуль mod_php, вы можете попытаться настроить maxrequests в httpd.conf, чтобы узнать, поможет ли это. Я бы попытался настроить, например, 10 - если это сработает, падение производительности не будет высоким, но утечек памяти быть не должно, даже при сильном скачке, когда используются все 250 httpd (10 * 250 = 2500 - на каждые 10 МБ памяти приходится 25 ГБ - так что, возможно, если у вас нет 128 ГБ ОЗУ, попробуйте также снизить количество процессов httpd, например, до 50).

Проверьте память в глобальном файле php.ini. не делайте это просто так, как 1 G и т. д. Я очень рекомендую, чтобы в эту учетную запись был добавлен локальный php.ini, чтобы не повлиять на весь сервер. Я бы порекомендовал установить глобальный лимит php.ini примерно на 64 МБ, поскольку этого обычно достаточно для большинства учетных записей.

тоже проверьте настройки apache