Как мне обращаться с файлами сеансов, которые становятся слишком многочисленными?

43

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

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

Мое решение - ночной crontab, который выполняет что-то вроде этого, find /path/to/magento/sessions/ -name "sess*" -type f -deleteно, по меньшей мере, чувствует себя не элегантно.

Каков наилучший способ справиться с этим?

Тоби
источник

Ответы:

37

Помимо удаления файлов сеанса с findиспользованием настраиваемого времени изменения, как указано другими, вы также можете:

  • Сохраните сессии в вашей базе данных . Конечно, это создаст нагрузку на вашу базу данных, и это не самый быстрый способ, но вы можете обрабатывать гораздо больше сеансов таким образом, и вы можете делиться сеансами между несколькими внешними серверами. Вы можете изменить настройку app/etc/local.xmlпутем переключения

    <session_save><![CDATA[files]]></session_save>

    в

    <session_save><![CDATA[db]]></session_save>
  • Используйте memcached в качестве хранилища сессии. Magento также поддерживает это по умолчанию. Посмотрите на app/etc/local.xml.additionalконфигурацию. Я никогда не использовал его в производстве, но слышал, что это может быть немного сложно.

  • Обработайте сеансы в Redis, используя блестящее расширение Colin Mollenhours Cm_RedisSession . Настройка Redis не должна занимать слишком много времени, также может использоваться для кэширования (см. Cm_Cache_Backend_Redis ) и сочетает в себе кэш-память ОЗУ с сохранением на диске (в отличие от memcached, RAM-дисков и т. П.), Что всегда в случае, если ваш сервер сбой.

Матиас Цейс
источник
1
Сохранение сеансов в базе данных также более безопасно. Если ваш файл .htaccess отсутствует (потому что кто-то удалил папку var), ваши файлы сеанса не будут доступны извне.
Эрфан
8
Сохранение сессий в базе данных является плохой идеей. Он не предназначен для этой цели, и MySQL является очень плохим инструментом для хранения сеансов, ключевой проблемой является блокировка - не говоря уже о встроенной поддержке очистки.
Бен Лессани - Сонасси
28

В случае файловых сессий они автоматически удаляются с помощью cron для очистки сессий PHP, поэтому файлы могут быть удалены в течение ~ 7200 секунд после создания. Таким образом, даже на загруженном сайте (30 тыс. Уникальных устройств в день) в каталоге ./var/session обычно содержится только около 4000 файлов сессий, что не годится даже для низкоуровневого Linux-сервера.

Тем не менее, очистка на самом деле зависит от работы cron, которая обычно не выглядит в каталоге ./var/session Magento. Таким образом, вы должны установить новую систему Cron

/usr/bin/find /home/myuser/public_html/var/session -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 -exec rm {} \; >/dev/null 2>&1

Период очистки по умолчанию для сеансов составляет 7200 секунд, что должно быть более чем достаточным, хотя вы можете изменить приведенное выше в соответствии с требованиями.

В сеансах Memcache TCP / IP - это единственные издержки, которые при развертывании с одним сервером замедляют работу по сравнению с файлами. Таким образом, вместо этого вы бы использовали сокет Unix, который устраняет эти издержки и повышает безопасность. Но даже при этом ваши сеансы клиентов будут сокращены / ограничены в зависимости от объема ОЗУ, которое вы можете выделить. Средний сеанс Magento составляет 4 КБ, поэтому вы сможете поддерживать 256 активных сеансов на каждый выделенный МБ. Поэтому не забудьте установить соответствующий лимит, чтобы клиенты не теряли случайно корзину / сессию. Также имейте в виду, что перезапуск демона Memcache уничтожит все существующие сеансы (ПЛОХО!).

С Redis (не нативным, но доступным через расширение) вы получаете уровень поддержки, аналогичный Memcache, но с дополнительными преимуществами постоянства (если вы захотите его использовать). С расширением Cm_Redis вы также сможете воспользоваться преимуществами сжатия сеансов. Мы обнаружили, что это расширение очень хорошо работает как в CE, так и в EE.

При использовании DB, по умолчанию срок действия чернослива составляет 1 неделя, поэтому в качестве примера приведенного выше размера хранилища (30 тыс. Уникальных единиц в день) вы будете смотреть на размер таблицы БД для core_cache_session около 7 ГБ, который будет расти Ваш магазин полностью остановлен, почти для каждой операции на основе сеанса.

Исходя из опыта хостинга как крупных (230 000 уникальных посетителей в день), так и небольших (<1 000 уникальных посетителей в день) магазинов, мы рекомендуем:

Развертывание на одном сервере - файлы

Развертывание на нескольких серверах - Redis (с использованием отдельной базы данных из основного кэша Magento)

Я написал несколько действительно подробных ответов здесь http://magebase.com/magento-tutorials/magento-session-storage-which-to-choose-and-why/comment-page-1/#comment-1980

Бен Лессани - Сонасси
источник
2
Если очистка cron предполагает очистку сессий, почему она терпит неудачу и как можно решить эту проблему вместо создания нового cron, который выглядит как обходной путь?
Гусь
12

Я задал связанный вопрос некоторое время назад:

https://stackoverflow.com/questions/7828975/php-garbage-collection-clarification

То, что я никогда не узнал (я оставил эту работу для новой, а исходная проблема стала чьей-то другой), так это то, будут ли сеансы Magento соответствовать этим настройкам, или если они реализуют обработку своих сеансов с использованием Zend (и, предположительно, своего рода zend.ini). файл конфигурации).

Настройки php для просмотра:

session.gc_maxlifetime session.gc_probability session.gc_divisor

http://php.net/manual/en/session.configuration.php#ini.session.gc-probability

pspahn
источник
Я хотел бы знать это сам, исходя из моего опыта, похоже, что Magento не соблюдает эти настройки (учитывая, что я получил ценность файлов сеансов в ГБ, можно с уверенностью предположить, что в какой-то момент GC сработал бы). Так что я просто установил рекомендованный сценарий Бена как работу cron, чтобы быть в безопасности.
Хавьер Вильянуэва
7

Обычно работы cron достаточно, но вот несколько вещей, о которых следует помнить:

1) Установите продолжительность сеанса не более session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) секунд (это настроит сеансы с истекшим сроком, которые будут подготовлены для сборки мусора php.ini или .htaccess)

2) Возможно, вы захотите сохранить сеансы в базе данных, см. Здесь для получения дополнительной информации о том, как это сделать (эта опция может быть проще управлять с помощью пользовательского модуля magento)

3) Другим вариантом, который стоит рассмотреть, является то, что Memcached Witch может также ускорить работу серверов (хотя и не полностью связанных с вопросом, я думаю, что это полезно знать)

См. Этот вопрос для получения дополнительной информации: https://stackoverflow.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept

pzirkind
источник
2
Использование cronjob для простого удаления всех файлов сеанса недопустимо. Что происходит, когда пользователь добавляет материал в свою корзину за 10 минут до запуска cron? Их корзина вытерта! Если сборка мусора в PHP не работает, это нужно выяснить.
Давидгер
+1 @ davidalger хорошая точка зрения, я был (ошибочно) полагал, что только истекшие сессии удалялись через cronjob
pzirkind
1
@davidalger - Собственная сборка мусора в PHP работает через cron. Он просто findхранит все файлы старше sess.gc_maxlifetimeи удаляет их. Удаление сеансов через cron - это нормальное, безопасное и приемлемое поведение.
Бен Лессани - Сонасси
1
На самом деле нет, это не так. Сборка мусора сеанса выполняется, когда запуск сеанса происходит во время выполнения сценариев PHP. Частота запуска сборки мусора зависит от значений session.gc_probabilityи session.gc_divisor. Если разные сценарии имеют разные значения, для session.gc_maxlifetimeодного с наименьшим значением будет определяться, как долго будет зависать содержимое, поскольку хранилище сеансов является глобальным, и выполнение этого сценария очистит другие объекты сеансов сценариев.
Давидгер
5

Во всех наших настройках у нас есть файл maintenance.php, который время от времени занимается очисткой журналов и каталога var. Поскольку сеансы должны быть либо сохранены в базе данных, либо в файловой системе, этот файл обслуживания очистит их обоих. (См. Код ниже).

Вы можете запустить следующую команду как задание cron для очистки журналов:

php maintenance.php clean=log

Приведенная выше команда выдаст следующий вывод:

catalogindex_aggregation has been truncated
catalogindex_aggregation_tag has been truncated
catalogindex_aggregation_to_tag has been truncated
catalog_compare_item has been truncated
dataflow_batch_export has been truncated
dataflow_batch_import has been truncated
log_customer has been truncated
log_quote has been truncated
log_summary has been truncated
log_summary_type has been truncated
log_url has been truncated
log_url_info has been truncated
log_visitor has been truncated
log_visitor_info has been truncated
log_visitor_online has been truncated
report_compared_product_index has been truncated
report_event has been truncated
report_viewed_product_index has been truncated

Вы можете запустить следующую команду как задание cron для очистки папки var:

php maintenance.php clean=var

Приведенная выше команда выдаст следующий вывод:

downloader/.cache/* has been emptied
downloader/pearlib/cache/* has been emptied
downloader/pearlib/download/* has been emptied
var/cache/ has been emptied
var/locks/ has been emptied
var/log/ has been emptied
var/report/ has been emptied
var/session/ has been emptied
var/tmp/ has been emptied

Фактический код (не забудьте указать путь к файлу local.xml):

<?php
$xml = simplexml_load_file('./app/etc/local.xml', NULL, LIBXML_NOCDATA);

$db['host'] = $xml->global->resources->default_setup->connection->host;
$db['name'] = $xml->global->resources->default_setup->connection->dbname;
$db['user'] = $xml->global->resources->default_setup->connection->username;
$db['pass'] = $xml->global->resources->default_setup->connection->password;
$db['pref'] = $xml->global->resources->db->table_prefix;

if (!isset($argv[1]) || !stristr($argv[1], 'clean=')) {
    echo 'Please use one of the commands below:' . PHP_EOL;
    echo 'php maintenance.php clean=log' . PHP_EOL;
    echo 'php maintenance.php clean=var' . PHP_EOL;
    die;
}

$method = str_replace('clean=', '', $argv[1]);

switch ($method) {
case 'log':
    clean_log_tables();
    break;
case 'var':
    clean_var_directory();
    break;
default:
    echo 'Please use one of the commands below:' . PHP_EOL;
    echo 'php maintenance.php clean=log' . PHP_EOL;
    echo 'php maintenance.php clean=var' . PHP_EOL;
    break;
}

function clean_log_tables() {
    global $db;

    $tables = array(
        'catalogindex_aggregation',
        'catalogindex_aggregation_tag',
        'catalogindex_aggregation_to_tag',
        'catalog_compare_item',
        'dataflow_batch_export',
        'dataflow_batch_import',
        'log_customer',
        'log_quote',
        'log_summary',
        'log_summary_type',
        'log_url',
        'log_url_info',
        'log_visitor',
        'log_visitor_info',
        'log_visitor_online',
        'report_compared_product_index',
        'report_event',
        'report_viewed_product_index'
    );

    mysql_connect($db['host'], $db['user'], $db['pass']) or die(mysql_error());
    mysql_select_db($db['name']) or die(mysql_error());

    foreach($tables as $v => $k) {
        @mysql_query('TRUNCATE `'.$db['pref'].$k.'`');
        echo $db['pref'] . $k . ' has been truncated' . PHP_EOL;
    }
}

function clean_var_directory() {
    $dirs = array(
        'downloader/.cache/*',
        'downloader/pearlib/cache/*',
        'downloader/pearlib/download/*',
        'var/cache/',
        'var/locks/',
        'var/log/',
        'var/report/',
        'var/session/',
        'var/tmp/'
    );

    foreach($dirs as $v => $k) {
        exec('rm -rf '.$k);
        echo $k . ' has been emptied' . PHP_EOL;
    }
}
Kenny
источник
5

Для Magento CMS и тому подобного (которые не очищают старые сессии) я просто использую задания cron на основе настроек php.ini.

PHP5 / Ubuntu 14.04 / Debian

Системная настройка cron.d для php5 не очищает Magento ./var/session (или что-либо, кроме папки сеанса по умолчанию (/ var / lib / php5 для Ubuntu и / var / lib / php5 / session или / tmp / для большинства других Linux). dists).

Но вы все равно можете использовать «sessionclean» и «maxlifetime» в соответствии с системным cron по умолчанию php5 / Debian:

Пример, который вы можете попробовать из командной строки:

# sudo /usr/lib/php5/sessionclean /var/www/{yoursite}/var/session $(/usr/lib/php5/maxlifetime)

Просто включите это в системный / корневой каталог или в пользовательский файл, у которого есть права на чтение / запись для файлов сеанса:

$ sudo crontab -e

Добавьте это, вы хотите, чтобы это выглядело как системный php cron:

20,40 * * * * [ -x /usr/lib/php5/maxlifetime ] && [ -x /usr/lib/php5/sessionclean ] && [ -d /var/www/*/var/session ] && /usr/lib/php5/sessionclean /var/www/{yoursite}/var/session $(/usr/lib/php5/maxlifetime)

или - поскольку мы знаем, что эти файлы / каталоги существуют:

20,40 * * * * /usr/lib/php5/sessionclean /var/www/*/var/session $(/usr/lib/php5/maxlifetime)

Теперь у меня есть управляемое количество сеансов, и оно поддерживается в чистоте с помощью сборки мусора / времени жизни по умолчанию с помощью настроек php.ini (cli).

(Вы можете оставить подстановочный знак выше или заменить на sitename.)

РЕДАКТИРОВАТЬ (PHP7 / Ubuntu 16.xx / Debian):

Сценарий 'sessionclean' был изменен, а скрипт maxlifetime был удален. Для задания system / php cron теперь это один скрипт. Вы больше не можете использовать это, поскольку вызовы файлов теперь статичны для скрипта.

Более старый сценарий php5 sessionclean все еще может работать для вас, если система не очищается . Что вы можете сделать, это взять старый пакет Debian php5 и извлечь sessioncleanего. Или вы можете просто скопировать это в свою область сценариев (предоставив надлежащие права / владелец / var / www / (site)):

#!/bin/sh

# first find all used files and touch them (hope it's not massive amount of files)
[ -x /usr/bin/lsof ] && /usr/bin/lsof -w -l +d "${1}" | awk -- '{ if (NR > 1) { print $9; } }' | xargs -i touch -c {}

# find all files older then maxlifetime
find "${1}" -depth -mindepth 1 -maxdepth 1 -ignore_readdir_race -type f -cmin "+${2}" -delete

Я также рекомендую переименовать его, чтобы он не путался с новым php 'sessionclean' cronjob. Затем вы можете подключить свой собственный номер «maxlifetime» следующим образом:

     20,40 * * * * /home/-username-/scripts/MySessionClean /var/www/*/var/session 61

(61 - это пример возраста (в минутах), а «MySessionClean» - переименованный скрипт php5, загруженный или скопированный сверху).

Таким образом, мы полностью избегаем вызовов php.ini / env.

(РЕДАКТИРОВАТЬ 13 ДЕКАБРЯ 2016 ГОДА: обновлена ​​ССЫЛКА РЕПО РЕГИОНА DEBIAN)

bshea
источник
3

Я регулярно очищал БД от всех этих старых файлов сессий. Ручная работа была раздражающей, пока я не установил Magento Optimizer, который делает всю эту рутинную работу для меня. Кроме того, мой кэш постоянно обновляется, и я не делаю это вручную после изменения продуктов и статических блоков. О да, сообщения об ошибках и заброшенные корзины также убираются.

Джеймс
источник
3

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

  1. Создайте имя файла «clean_session.sh» в вашей magentoпапке.
  2. Вставьте эти строки.

#!/bin/bash
# delete session files older than 14 days
find /home/DOMAIN/public_html/var/session -name 'sess_*' -type f -mtime +14 -exec rm {} \;

  1. Затем вы можете запланировать cronjob еженедельно выполнять уборку.

1 1 * * 6 /bin/sh /home/DOMAIN/public_html/clean_session.sh

  1. Не забудьте сделать файл исполняемым как

chmod u+x clean_session.sh

  1. И вы также можете запустить его как

sh clean_session.sh

индиго
источник
3

В моем случае я запускаю этот скрипт, расположенный в magento/var/каталоге, для удаления файлов сессий старше одной недели ( -mtime +7):

#!/bin/sh
# Place this script in magento/var/ directory

for n in `seq 0 9`
  do
    for u in `seq 0 9`
    do
      for m in `seq 0 9`
        do
          name="sess_"$n$u$m*
          echo $name
          find session/ -name $name -type f -mtime +7 -delete
          echo $name ok
      done
      for m in {a..z}
        do
          name="sess_"$n$u$m*
          echo $name
          find session/ -name $name -type f -mtime +7 -delete
          echo $name ok
      done
    done
      for u in {a..z}
      do
        for m in `seq 0 9`
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
        for m in {a..z}
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
    done
done

for n in {a..z}
  do
    for u in `seq 0 9`
      do
        for m in `seq 0 9`
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
        for m in {a..z}
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
    done
    for u in {a..z}
      do
        for m in `seq 0 9`
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
        for m in {a..z}
          do
            name="sess_"$n$u$m*
            echo $name
            find session/ -name $name -type f -mtime +7 -delete
            echo $name ok
        done
    done
done

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

Этот скрипт можно получить по адресу: https://gist.github.com/Nolwennig/a75dc2f8628be2864bb2.

Nolwennig
источник
0

Я создал скрипт, который очищает каталог var / session. Вы можете добавить его в задание cron, чтобы запускать его раз в день, которого должно быть достаточно, и при необходимости корректировать. Вы заметите, что когда каталог вашей сессии заполнен, невозможно удалить файлы с помощью cpanel или ssh, этот скрипт просто сделает свое дело в корневом каталоге magento.

<?php
function adjustSessionFiles($dir, $pattern = "*")
{
    $files = glob($dir . "/$pattern");
    foreach ($files as $file) {
        if (is_dir($file) and !in_array($file, array('..', '.')))  {
            adjustSessionFiles($file, $pattern);
        }else if(is_file($file) and ($file != __FILE__)) {
            unlink($file);
        }
    }
}
$dir = __DIR__ . DIRECTORY_SEPARATOR . 'var' . DIRECTORY_SEPARATOR . 'session';
adjustSessionFiles($dir);
Лоуренс Фарбман
источник
Проблема этого скрипта в том, что он удаляет все сессии, а не только старые. Таким образом, никто не может войти в систему дольше, чем за день (если вы запускаете это ежедневно), и все корзины будут пустыми после этого (так что ни одна корзина не будет держаться дольше, чем день).
Симонтессор