Як мені обробляти файли сеансу, які стають занадто численними?


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 ) та поєднує кеш оперативної пам'яті зі стійкістю на диску (на противагу запам’ятовуваним, дискам оперативної пам’яті тощо), що завжди є у випадку, якщо ваш сервер є врізатися.


1
Збереження сеансів у базі даних також є більш безпечним. Якщо вашого файлу .htaccess немає (оскільки хтось видалив папку var), файли сеансу не будуть доступні зовні.
Ерфан

8
Збереження сесій у базі даних - погана ідея. Він не призначений для цієї мети, і MySQL служить дуже поганим інструментом для зберігання сеансів, блокування є ключовою проблемою - не кажучи вже про відсутність вбудованої підтримки для продувки.
Бен Лессані - Сонассі

28

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

Однак прибирання фактично покладається на роботу з кроном - що зазвичай не знаходиться в каталозі ./var/session в Magento. Тож вам слід створити новий системний крон

/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 знищить усі існуючі сеанси (BAD!).

З Redis (не рідним, але доступним через розширення) ви отримуєте такий же рівень підтримки, як Memcache, але з додатковими перевагами наполегливості (якщо ви бажаєте ним користуватися). З розширенням Cm_Redis ви також зможете скористатися компресією сеансу. Ми виявили, що це розширення працює дуже добре як для розгортання CE, так і для EE.

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

З досвіду хостингу як великих (230 тис. Унікальних відвідувачів на день), так і невеликих (<1 к унікальних відвідувачів на день) магазинів, наша рекомендація:

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

Розгортання декількох серверів - Redis (використовуючи окрему базу даних з основного кешу Magento)

Я написав тут справді ґрунтовні відповіді http://magebase.com/magento-tutorials/magento-session-storage-which-to-choose-and-why/comment-page-1/#comment-1980


2
Якщо очищувальний крон передбачає очищення сеансів, то чому він виходить з ладу, і як можна усунути цю проблему замість створення нового крона, який відчуває себе як обхід?
Гусь

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


Я хотів би це знати сам, з мого досвіду, схоже, що Magento не шанує ці налаштування (враховуючи, що я отримав великі файли сеансів в ГБ, можна було б припустити, що в якийсь момент GC спрацює). Тож я просто встановив рекомендований Бен сценарій, як безпечну роботу.
Хав'єр Віллануєва

7

Зазвичай роботи з хроном достатньо, але тут слід пам’ятати кілька речей:

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


2
Використовувати cronjob для простого видалення всіх файлів сеансу неприпустимо. Що відбувається, коли користувач додає речі у свою кошик за 10 хвилин до запуску крона? Їх кошик витирають чисто! Якщо збирання сміття PHP не працює, це потрібно з’ясувати.
davidalger

+1 @davidalger Хороший момент, я був за (помилковим) припущенням, що через cronjob видаляються лише сесії, що минули, що минули,
pzirkind

1
@davidalger - власне збирання сміття PHP працює через cron. Він просто findмістить усі файли старші sess.gc_maxlifetimeта видаляє їх. Видалення сеансів через cron - це нормальна, безпечна та прийнятна поведінка.
Бен Лессані - Сонассі

1
Власне, ні, це не так. Збір сміття сеансу проводиться, коли старт запуску відбувається під час виконання сценаріїв PHP. Те, наскільки часто проводиться збирання сміття, залежить від значень session.gc_probabilityта session.gc_divisor. Якщо різні сценарії мають різні значення, session.gc_maxlifetimeтой, який має найменше значення, визначає, як довго висить матеріал, оскільки зберігання сеансу є глобальним і виконання сценарію очистить інші об'єкти сеансів скриптів.
davidalger

5

У всіх наших налаштуваннях у нас є файл vzdrže.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;
    }
}

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 дисти).

Але ви все одно можете використовувати "sessionclean" та "maxlifetime" відповідно до системного крона php5 / Debian за замовчуванням:

Приклад ви можете спробувати з командного рядка:

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

Тому просто включіть це в систему / root crontab або в crontab користувача, який прочитав / записув дозвіл на файли сеансу:

$ sudo crontab -e

Додайте, це ви хочете, щоб він виглядав схожим на system 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).

(Ви можете залишити підстановку вище або замінити ім'ям сайту.)

EDIT (PHP7 / Ubuntu 16.xx / Debian):

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

Старіший скрипт php5 sessionclean все ще може працювати для вас, якщо система не очищається . Що ви можете зробити, це взяти старіший пакет Debian php5 та витягнути sessioncleanз нього. Або ви можете просто скопіювати це в область сценаріїв (надавши належні / var / www / (сайт) дозволи / права власності):

#!/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

Я також рекомендую перейменувати його, щоб його не плутали з новим cp-джоубом php 'sessionclean'. Потім ви можете підключити власний номер "максимального життя" таким чином:

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

(61 - приклад віку (в хвилинах), а "MySessionClean" - перейменований скрипт php5, завантажений або скопійований зверху).

Таким чином, ми уникаємо php.ini / env дзвінків повністю.

(РЕДАКЦІЯ 13DEC2016: ОНОВЛЕННЯ ДЕРЖАВНОГО АРХІВУ РЕПО ЛІНКУ)


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. Тоді ви можете запланувати графік роботи на тиждень, щоб виконувати прибирання.

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


0

Я створив сценарій, який очищає каталог var / session. Ви можете додати його в роботу з кроном, яку потрібно виконувати один раз на день, що має бути достатньо, і коригувати за потребою. Ви помітите, коли ваш сеансовий каталог заповнюється, видалити файли через 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);

Проблема цього сценарію полягає в тому, що він видаляє всі сеанси, не тільки старі. Таким чином, ніхто не може входити в систему довше, ніж за день (якщо ви запускаєте цей день), і всі візки будуть порожніми після цього (тому жоден візок не буде тривати більше дня).
simonthesorcerer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.