28.12. Оптимизация сеансов работы с дисками
Многие Web-приложения для сохранения информации о продолжительности посещения конкретными пользователями пользуются HTTP-сеансами. Стандартным и наиболее используемым способом хранения информации о сеансах являются дисковые файлы, размещенные в каталоге /tmp. Для загруженных Web-узлов, обслуживающих большое количество пользователей, осуществление доступа к файлам хранения информации о сеансах может стать предельно неэффективным, так как большинство файловых систем (включая файловую систему ext2, используемую в ОС Linux, и файловую систему NTFS, используемую в ОС Windows) не имеет возможности эффективно обрабатывать большое количество файлов из одного и того же каталога. По мере того как количество файлов в каталоге /tmp увеличивается в связи с большим количеством активных сеансов, увеличивается и время, необходимое для открытия новых сессий. 
Хорошим первым шагом является перенос каталога хранения информации о сеансах из /tmp в каталог, который был бы специально отведен под файлы с такой информацией. Это можно сделать с помощью директивы session.save_path в конфигурационном файле php.ini. Использование другого каталога позволяет избежать накладных расходов, связанных с обработкой файлов, не имеющих отношения к файлам информации по сеансам PHP, как это бывает в случае их наличия в каталоге /tmp. Однако это всего лишь первый шаг, и не обязательно самый существенный. При наличии большого количества сеансов количество других файлов в каталоге /tmp может быть незначительным.
И как обычно, на помощь приходит PHP, позволяя разработчику легко распределить файлы с информацией о сеансах в разных каталогах. PHP имеет встроенную поддержку рассмотрения первых n букв в ключе сеанса в качестве каталогов хеширования. Проиллюстрируем это для тех, кто не очень знаком с данной методологией. Предположим, что у нас есть сеанс с ключом 3fdb6cd5 74 8e5ef2ecc41553 0a3f16 7e и что директивой session.save_path был задан каталог /tmp/php_sessions. PHP сохранит этот сеанс в файле /tmp/php_sessions/sess_3fdb6cd5748e5ef2 ecc415530a3f167e. Однако, если мы заменим в конфигурационном файле php.ini строку session.save_path = 2;/tmp/php_sessions, PHP сохранит информацию о сеансе в файле /tmp/php_sessions/3/f/sess_3fdb6cd5748e5ef2ecc415530a 3f167e. Обратите внимание на дополнительные каталоги, разделяющие каталог php_sessions и сам файл сеансов. Аналогично, задав директиву session.save_ path равной 4;/tmp/php_sessions, PHP будет сохранять файл сеанса в /tmp/php_sessions/3/f/d/b/sess_3fdb6cd5748e5ef2ecc415530a3f167e. Необязательное число, заданное в session.save_path и разделенное точками с запятыми, называется глубиной пути сохранения сеанса.
Благодаря экспоненциальной природе этого алгоритма количество файлов в каталоге уменьшается в степени 36, что равно глубине пути сохранения сеанса, а 36 является количеством символов, использованных для идентификаторов сеанса. Это значит, что, как правило, нет необходимости создавать глубину больше 2 или 3.
Можно усовершенствовать и процесс сбора мусора, который представляет собой процесс удаления файлов с информацией о старых сессиях по истечении определенного времени. По умолчанию PHP занимается сбором мусора автоматически, однако из-за архитектурных ограничений встроенная процедура сбора мусора PHP проводится в ходе выполнения запроса. Это значит, что последний запрос будет заблокирован на протяжении времени, необходимого для очистки, которая иногда занимает несколько секунд. Более того, автоматизированная очистка PHP поддерживает по умолчанию установку глубины, равную 0. Как только нам потребуется изменить глубину, автоматическая сборка мусора перестает функционировать, и файлы сеансов начинают накапливаться.
Лучшим решением для сборки мусора является передача этой процедуры утилите cron. Например, если необходимо удалять сеансы каждые 24 часа и выполнять сборку каждый час, необходимо задать в файле crontab строку следующего вида:
0 * * * * nobody find /tmp/php_sessions -name sess_* -ctime +1 | xargs rm -f
Использование этого механизма справится с любой глубиной, заданной директивой session.save_path, и позволит избежать накопления всяческого мусора. Кроме того, эта процедура позволяет задать любую периодичность сбора мусора или изменить сроки хранения файла сеанса с помощью различных установок команды find.