Задание cron для сборки мусора в Ubuntu для сессий PHP занимает 25 минут, почему?

13

В Ubuntu настроено задание cron, которое ищет и удаляет старые сессии PHP:

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] \
   && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
   fuser -s {} 2> /dev/null \; -delete

Моя проблема в том, что этот процесс занимает очень много времени, с большим количеством дискового ввода-вывода. Вот мой график использования процессора:

График использования процессора

Ход очистки представлен шипами чирка. В начале периода работы PHP по очистке планировались по умолчанию 09 и 39 минут. В 15:00 я удалил 39-минутное время из cron, так что задание по очистке, в два раза превышающее размер, выполняется вдвое реже (вы можете видеть, что пики становятся в два раза шире и вдвое реже).

Вот соответствующие графики для времени ввода-вывода:

Время IO

И дисковые операции:

Дисковые операции

На пике, где было около 14 000 активных сеансов, можно увидеть, что очистка выполняется в течение полных 25 минут, очевидно, используя 100% одного ядра ЦП и что, по-видимому, составляет 100% дискового ввода-вывода за весь период. Почему это так ресурсоемко? lsКаталога сеанса /var/lib/php5занимает всего долю секунды. Так почему же на обрезку старых сессий уходит целых 25 минут? Что я могу сделать, чтобы ускорить это?

Файловая система для этого устройства в настоящее время ext4, работает на 64-битной Ubuntu Precise 12.04.

РЕДАКТИРОВАТЬ: я подозреваю, что загрузка происходит из-за необычного процесса "fuser" (так как я ожидаю, что простой rmбудет чертовски быстрее, чем производительность, которую я вижу). Я собираюсь отказаться от использования термоэлемента и посмотреть, что произойдет.

thenickdude
источник
Сколько трафика получает ваш веб-сайт для генерации такого количества сеансов?
Майкл Хэмптон

Ответы:

9

Удаление fuserдолжно помочь. Это задание запускает fuserкоманду (проверьте, открыт ли файл в настоящее время) для каждого найденного файла сеанса , что может легко занять несколько минут в загруженной системе с 14k сеансами. Это была ошибка Debian (Ubuntu основана на Debian).

Вместо memcached вы также можете попытаться использовать tmpfs (файловую систему в памяти) для файлов сеансов. Как и memcached, это приведет к аннулированию сессий при перезагрузке (это можно обойти, сделав резервную копию этого каталога где-нибудь в сценарии завершения работы и восстановив в сценарии запуска), но будет намного проще в настройке. Но это не поможет с fuserпроблемой.

Tometzky
источник
Похоже, ошибка в fuser заключалась в том, что более ранняя версия разветвлялась, но затем не была завершена после завершения, оставляя тысячи fuserпроцессов в памяти, потребляющей состояние зомби, что приводит к сбою сервера. Я думаю, что это уже было исправлено в версии psmisc, которую я использую.
thenickdude
Это еще одна ошибка. У вас есть простая проблема запуска тысяч fuserпроцессов, которые все должны искать в /proc/открытых файлах.
Томецкий
9

Поздравляем с тем, что у вас есть популярный веб-сайт и все это время он работает на виртуальной машине.

Если вы на самом деле тянет в двух миллионов просмотров страниц в день, то вы собираетесь складывают ЛО PHP сессий в файловой системе, и они собираются занять много времени , чтобы удалить , независимо от того , используете ли вы fuserили rmили в пылесос.

На этом этапе я бы порекомендовал вам рассмотреть альтернативные способы хранения ваших сессий:

  • Один из вариантов - хранить сессии вmemcached . Это молниеносно, но если сервер падает или перезагружается, все ваши сеансы будут потеряны, и все выйдут из системы.
  • Вы также можете хранить сессии в базе данных. Это будет немного медленнее, чем memcached, но база данных будет постоянной, и вы сможете очистить старые сессии простым SQL-запросом. Чтобы реализовать это, вы должны написать собственный обработчик сеанса .
Майкл Хэмптон
источник
Memcached, безусловно, является вариантом, хотя он должен быть отдельным пулом от нашего основного экземпляра memcached, в противном случае сеансы будут случайным образом исключены из нашего давления кеша. Я не уверен, что удаление 14 000 файлов должно занять 25 минут. Это звучит слишком медленно для меня. Я подожду пару часов и посмотрю, на что rmпохоже простое исполнение .
thenickdude
Не зная больше о вашей общей архитектуре, я не решаюсь рекомендовать одно поверх другого.
Майкл Хэмптон
Вы можете объединить серверы Memcached для резервирования, установив memcache.session_redundancy = 2. См. Serverfault.com/questions/164350/… . Redis - хороший вариант, если вы беспокоитесь о сохранности и гораздо быстрее, чем хранилища баз данных SQL.
jfountain
4

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

Но в ходе тестирования производительности я обнаружил, что огромные затраты на поддержку этого обслуживания сеанса почти полностью зависят от необходимости fuserвыполнения задания cron. Вот графики производительности после возврата к заданию Natron / Oneiric cron, в котором rmвместо fuserобрезки старых сессий переключение происходит в 2:30.

использование процессора

Истекшее время ввода-вывода

Дисковые операции

Вы можете видеть, что периодическое снижение производительности, вызванное очисткой сеанса PHP в Ubuntu, почти полностью устранено. Пики, показанные на графике «Дисковые операции», теперь намного меньше по величине и примерно такие же тонкие, как этот график, возможно, измерить, показывая небольшое короткое нарушение, когда ранее производительность сервера значительно снижалась в течение 25 минут. Избыточное использование ЦП полностью исключено, теперь это работа, связанная с IO.

(несвязанное задание ввода-вывода выполняется в 05:00, а задание ЦП выполняется в 7:40, что приводит к пикам на этих графиках)

Модифицированная работа cron, которую я сейчас выполняю:

09 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && \
   [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 \
   | xargs -n 200 -r -0 rm
thenickdude
источник
-print0 | xargs ...не нужно - вы могли бы просто уйти -deleteтуда. Но он будет работать в обоих направлениях с сопоставимой скоростью.
Томецкий
1

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

В описанном сценарии OP использовал ext4. Каталоги в ext4 хранят данные файлов в формате базы данных htree - это означает, что удержание большого количества файлов в одном каталоге незначительно по сравнению с распределением их по разным каталогам. Это не относится ко всем файловым системам. Обработчик по умолчанию в PHP позволяет вам использовать несколько подкаталогов для файлов сессий (но учтите, что вы должны проверить, что управляющий процесс повторяется в этих каталогах - работа cron выше не делает).

Большая часть стоимости операции (после удаления вызова fuser) возникает из-за просмотра файлов, которые еще не устарели. Использование (например) одного уровня подкаталогов и 16 заданий cron, просматриваемых в каждом подкаталоге (0 /, 1 /, ... d /, e /, f /), сгладит возникающие нагрузки.

Использование собственного обработчика сеанса с более быстрой подложкой поможет - но есть из чего выбирать (memcache, redis, mysql handler socket ...), оставляя в стороне диапазон качества, опубликованных в Интернете, который вы выбираете, зависит от точного требования в отношении вашего приложения, инфраструктуры и навыков, не забывайте, что часто есть различия в обработке семантики (особенно блокировка) по сравнению с обработчиком по умолчанию.

symcbean
источник
0

С таким трафиком вы не должны ставить сессии на диск. Вы должны использовать что-то вроде memcache. Все, что вам нужно сделать, это настроить php, и изменение кода не потребуется. Смотри например

http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/

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

Майк
источник