너무 많은 세션 파일을 어떻게 처리해야합니까?


43

Magento 사이트를 보유하고 있고 때로는 세션 파일로 가득 찬 두 서버의 sysadmin으로 활동하고 있습니다.

나는이 파일을 관리하는 것이 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구성을 살펴보십시오 . 나는 그것을 생산에 사용한 적이 없지만 조금 까다로울 수 있다고 들었습니다.

  • Colin Mollenhours 화려한 확장 Cm_RedisSession을 사용하여 Redis세션을 처리하십시오 . Redis를 설정하는 데 너무 오래 걸리지 않아야하며 캐싱에 사용될 수도 있고 ( Cm_Cache_Backend_Redis 참조 ), 서버가 항상있는 경우에 대비하여 RAM 캐시와 디스크의 지속성 (memcached, RAM 디스크 등)을 결합합니다. 충돌.


1
데이터베이스에 세션을 저장하는 것이 더 안전합니다. 누군가가 var 폴더를 삭제했기 때문에 .htaccess 파일이 없으면 외부에서 세션 파일에 액세스 할 수 없습니다.
Erfan

8
데이터베이스에 세션을 저장하는 것은 나쁜 생각입니다. 이 목적을 위해 설계되지 않았으며 MySQL은 세션 저장을위한 매우 열악한 도구로서 역할을합니다.
Ben Lessani-Sonassi

28

파일 기반 세션의 경우 PHP 세션 정리 크론에 의해 자동 정리되므로 파일이 생성 된 후 ~ 7200 초 내에 삭제 될 수 있습니다. 따라서 사용량이 많은 사이트 (하루에 30k 고유)에서도 ./var/session에는 약 4,000 개의 세션 파일 만 있습니다. 이는 저급 Linux 서버에는 해당되지 않습니다.

그러나 정리는 실제로 크론 작동에 의존합니다. 일반적으로 Magento의 ./var/session 디렉토리에는 표시되지 않습니다. 새로운 시스템 크론을 설정해야합니다

/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는 유일한 오버 헤드입니다. 단일 서버 배포의 경우 파일 기반보다 속도가 느려집니다. 따라서 대신 유닉스 소켓을 사용하면 오버 헤드가 제거되고 보안이 향상됩니다. 그러나 여전히 그렇더라도 고객 세션은 할당 할 수있는 RAM의 양에 따라 잘 리거나 제한됩니다. 평균 Magento 세션은 4Kb이므로 할당 한 MB 당 256 개의 활성 세션을 지원할 수 있습니다. 따라서 고객이 카트 / 세션을 임의로 잃지 않도록 적절한 제한을 설정해야합니다. 또한 Memcache 데몬을 다시 시작하면 기존 세션 (BAD!)이 모두 지워집니다.

Redis (기본은 아니지만 확장을 통해 사용 가능)를 사용하면 Memcache와 비슷한 수준의 지원을받을 수 있지만 지속성의 이점이 추가됩니다 (사용하려는 경우). Cm_Redis 확장을 사용하면 세션 압축을 활용할 수도 있습니다. 이 확장은 CE 및 EE 배포 모두에서 매우 잘 작동합니다.

with with DB, 기본 정리 제거 만료 설정은 1 주일이므로 위의 상점 크기 (예 : 하루 30k 고유)를 사용하면 약 7GB의 core_cache_session에 대한 DB 테이블 크기를 볼 수 있습니다. 거의 모든 세션 기반 작업에 대해 상점을 완전히 정지시킵니다.

대규모 (하루에 고유 한 방문자 수 230k) 및 소규모 (하루에 고유 한 방문자 수 <1k) 모두 호스팅 한 경험에서 권장 사항은 다음과 같습니다.

단일 서버 배포-파일

다중 서버 배포-Redis (기본 Magento 캐시와 별도의 데이터베이스 사용)

나는 여기에 정말 철저한 답장을 썼습니다 .


2
정리 cron이 세션을 지우는 것으로 가정하면 왜 실패합니까? 해결 방법처럼 느껴지는 새로운 cron을 만드는 대신 어떻게 문제를 해결할 수 있습니까?
Goose

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가 이러한 설정을 존중하지 않는 것처럼 보입니다 (GB의 세션 파일을 확보 한 것을 고려하면 어느 시점에서 GC가 트리거되었다고 가정하는 것이 안전합니다). 그래서 방금 Ben이 권장하는 스크립트를 크론 작업으로 설정하여 안전했습니다.
Javier Villanueva

7

일반적으로 크론 작업이면 충분하지만 다음은 명심해야 할 몇 가지 사항입니다.

1) 세션을 session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) 초 이하로 설정하십시오 (php.ini 또는 .htaccess에 의해 가비지 콜렉션을 준비하기 위해 만료 된 세션이 설정됩니다)

2) 데이터베이스에 세션을 저장하고 싶을 수도 있습니다.이 작업을 수행하는 방법에 대한 자세한 내용은 여기 를 참조 하십시오 (이 옵션은 사용자 지정 magento 모듈을 통해 관리하기가 더 쉬울 수 있음)

3) 고려해야 할 또 다른 옵션은 Memcached 마녀가 서버 속도를 높일 수도 있다는 것입니다 (질문에 완전히 연결되지는 않았지만 알고있는 것이 유용하다고 생각합니다)

자세한 내용은이 질문을 참조하십시오 : https : //.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept


2
cronjob을 사용하여 모든 세션 파일을 간단히 제거하는 것은 허용되지 않습니다. cron이 실행되기 10 분 전에 사용자가 장바구니에 물건을 추가하면 어떻게됩니까? 그들의 손수레는 깨끗하게 닦입니다! PHP의 가비지 콜렉션이 작동하지 않으면이를 알아 내야합니다.
davidalger

+1 @davidalger 좋은 지적, 나는 만료 된 세션 만 cronjob을 통해 삭제되었다는 가정 (실종) 가정에 있었다
pzirkind

1
@davidalger-PHP 자체 가비지 수집은 cron을 통해 작동합니다. 단순히 find모든 파일보다 오래된 파일 sess.gc_maxlifetime을 제거하고 제거합니다. cron을 통한 세션 삭제는 정상적이고 안전하며 허용 가능한 동작입니다.
Ben Lessani-Sonassi

1
사실은 아닙니다. 세션 가비지 콜렉션은 PHP 스크립트 실행 중 세션 시작이 발생하면 완료됩니다. 가비지 수집이 실행되는 빈도는 session.gc_probability및 의 값에 따라 다릅니다 session.gc_divisor. 다른 스크립트의 session.gc_maxlifetime값이 가장 낮은 스크립트의 값이 다른 경우 세션 저장소가 전역 적이므로 해당 스크립트의 실행으로 인해 다른 스크립트 세션 개체가 정리되므로 시간이 얼마나 걸리는지 결정합니다.
davidalger

5

모든 설정에는 로그 및 var 디렉토리의 정리를 관리하는 maintenance.php 파일이 있습니다. 세션은 데이터베이스 나 파일 시스템에 저장되어야하므로이 유지 보수 파일은 세션을 모두 정리합니다. (아래 코드 참조).

다음 명령을 크론 작업으로 실행하여 로그를 정리할 수 있습니다.

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 등의 경우 php.ini 설정에 따라 cron 작업을 사용합니다.

PHP5 / 우분투 14.04 / 데비안

php5에 대한 시스템 cron.d 설정은 Magento ./var/session (또는 기본 세션 폴더 (Ubuntu의 경우 / var / lib / php5 및 / var / lib / php5 / sessions 또는 / tmp /) dists).

그러나 기본 php5 / Debian 시스템 크론에 따라 "sessionclean"및 "maxlifetime"을 계속 사용할 수 있습니다.

예를 들어 명령 행에서 시도 할 수 있습니다.

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

따라서 시스템 / 루트 crontab 또는 세션 파일에 대한 읽기 / 쓰기 권한이있는 사용자 crontab에이를 통합하십시오.

$ 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) 설정을 통해 기본 가비지 수집 / 수명을 통해 깨끗하게 유지됩니다.

(와일드 카드를 그대로 두거나 사이트 이름으로 바꿀 수 있습니다.)

편집 (PHP7 / Ubuntu 16.xx / Debian) :

'sessionclean'스크립트가 변경되었으며 maxlifetime 스크립트가 제거되었습니다. system / php cron 작업의 경우 이제 하나의 스크립트입니다. 파일 호출이 이제 스크립트에 정적 인 상태이므로 더 이상 이것을 사용할 수 없습니다.

시스템이 정리되지 않으면 이전 php5 sessionclean 스크립트가 여전히 작동합니다. 당신이 할 수있는 일은 오래된 데비안 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 호출을 완전히 피합니다.

(편집 13DEC2016 : 업데이트 된 DEBIAN ARCHIVE REPO LINK)


3

이전의 모든 세션 파일에서 DB를 역으로 정리했습니다. 이 모든 일상적인 작업을 수행하는 Magento Optimizer 를 설치할 때까지 수동 작업을 자극했습니다 . 또한 캐시가 지속적으로 새로 고쳐지고 제품 및 정적 블록을 변경 한 후 수동으로 캐시를 업데이트하지 않습니다. 예, 오류 보고서와 버려진 카트도 청소됩니다.


3

위의 모든 의견 중 이것이 쉬운 해결책이라고 생각하며 오래된 스크립트 파일을 관리하고 새 세션 파일을 유지하기 위해 긴 스크립트와 타사 확장을 설치하는 것보다 낫기를 바랍니다.

  1. magento폴더 아래에 "clean_session.sh"파일 이름을 작성하십시오 .
  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/1 주일 이상 지난 세션 파일을 삭제하기 위해 디렉토리 에있는이 스크립트를 실행합니다 ( -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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.