Làm cách nào để xử lý các tệp phiên trở nên quá nhiều?


43

Tôi đang hoạt động như một sysadmin cho một vài máy chủ chứa các trang Magento và đôi khi chúng chứa đầy các tệp phiên.

Tôi đã được thông báo rằng việc quản lý các tệp này không phải là điều có thể được thực hiện từ bên trong Magento và tôi cho rằng việc sử dụng tạm thời của chúng có nghĩa là chúng không thể bị tắt, nhưng có vẻ kỳ lạ là Magento không có cách nào để xử lý việc loại bỏ chúng các tập tin?

Giải pháp của tôi là một crontab hàng đêm thực hiện một cái gì đó như thế này find /path/to/magento/sessions/ -name "sess*" -type f -deletenhưng nó cảm thấy không phù hợp để nói ít nhất.

Cách tốt nhất để xử lý những điều này là gì?

Câu trả lời:


37

Ngoài việc xóa các tệp phiên bằng findcách sử dụng thời gian sửa đổi tùy chỉnh như được đề cập bởi người khác, bạn cũng có thể:

  • Lưu các phiên trong cơ sở dữ liệu của bạn . Tất nhiên, điều này sẽ đặt tải vào cơ sở dữ liệu của bạn và đó không phải là cách nhanh nhất, nhưng bạn có thể xử lý nhiều phiên hơn theo cách đó và bạn có thể chia sẻ phiên giữa nhiều máy chủ ngoại vi. Bạn có thể thay đổi cài đặt app/etc/local.xmlbằng cách chuyển đổi

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

    đến

    <session_save><![CDATA[db]]></session_save>
  • Sử dụng memcached như lưu trữ phiên của bạn. Magento cũng hỗ trợ điều này theo mặc định. Có một cái nhìn app/etc/local.xml.additionalcho cấu hình. Tôi chưa bao giờ sử dụng nó trong sản xuất nhưng đã nghe nói rằng điều này có thể là một chút khó khăn.

  • Xử lý các phiên trong Redis bằng Cm_RedisSession mở rộng tuyệt vời của Colin Mollenhours . Thiết lập Redis không mất quá nhiều thời gian, cũng có thể được sử dụng để lưu vào bộ đệm (xem Cm_Cache_Backend_Redis ) và kết hợp bộ đệm RAM với sự tồn tại trên đĩa (đối lập với memcached, đĩa RAM hoặc tương tự) luôn luôn trong trường hợp máy chủ của bạn va chạm.


1
Lưu các phiên trong cơ sở dữ liệu cũng an toàn hơn. Nếu tệp .htaccess của bạn không có ở đó (vì ai đó đã xóa thư mục var), các tệp phiên của bạn sẽ không thể truy cập được từ bên ngoài.
Erfan

8
Lưu các phiên trong cơ sở dữ liệu là một ý tưởng tồi. Nó không được thiết kế cho mục đích đó và MySQL hoạt động như một công cụ rất kém để lưu trữ phiên, khóa là một vấn đề quan trọng - chưa kể đến việc không hỗ trợ tích hợp cho việc thanh trừng.
Ben Lessani - Sonassi

28

Với các phiên dựa trên tệp, chúng sẽ được tự động cắt xén bởi cron dọn dẹp phiên PHP - vì vậy các tệp có thể sẽ bị xóa trong vòng ~ 7200 giây sau khi tạo. Vì vậy, ngay cả trên một trang web bận rộn (30k đơn vị mỗi ngày), thường chỉ có khoảng 4.000 tệp phiên trong ./var/session - không có gì ngay cả đối với máy chủ Linux cấp thấp.

Tuy nhiên, việc dọn dẹp thực sự phụ thuộc vào cron làm việc - thường không tìm trong thư mục ./var/session của Magento. Vì vậy, bạn nên thiết lập một cron hệ thống mới

/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

Thời gian dọn dẹp mặc định cho các phiên là 7200 giây, mức này là quá đủ, mặc dù bạn có thể thay đổi điều trên cho phù hợp.

Với các phiên Memcache, TCP / IP là chi phí duy nhất - mà đối với việc triển khai một máy chủ, sẽ làm cho nó chậm hơn so với dựa trên tệp. Vì vậy, sau đó, bạn sẽ sử dụng một ổ cắm unix thay thế, loại bỏ chi phí đó và bảo mật tốt hơn. Nhưng ngay cả khi vẫn còn, các phiên khách hàng của bạn sẽ bị cắt / giới hạn về số lượng RAM bạn có thể phân bổ. Phiên Magento trung bình là 4Kb - vì vậy bạn sẽ có thể hỗ trợ 256 phiên hoạt động, trên mỗi MB bạn phân bổ. Vì vậy, hãy chắc chắn đặt giới hạn phù hợp để tránh khách hàng mất ngẫu nhiên giỏ hàng / phiên. Và cũng lưu ý, khởi động lại Memcache daemon sẽ xóa sạch tất cả các phiên hiện có (BAD!).

Với Redis (không phải bản địa, nhưng có sẵn thông qua tiện ích mở rộng), bạn sẽ nhận được mức hỗ trợ tương tự như Memcache, nhưng với các lợi ích bổ sung của sự kiên trì (nếu bạn muốn sử dụng nó). Với tiện ích mở rộng Cm_Redis, bạn cũng có thể tận dụng tính năng nén phiên. Chúng tôi đã tìm thấy tiện ích mở rộng này hoạt động rất tốt trên cả triển khai CE và EE.

Với DB, cài đặt hết hạn cắt tỉa mặc định là 1 tuần, vì vậy với quy mô cửa hàng ở trên là một ví dụ (30k đơn vị mỗi ngày), bạn sẽ xem kích thước bảng DB cho core_cache_session khoảng 7GB - sẽ nghiền cửa hàng của bạn tạm dừng hoàn toàn, cho hầu hết mọi hoạt động dựa trên phiên.

Từ kinh nghiệm lưu trữ cả cửa hàng lớn (230k khách truy cập mỗi ngày) và cửa hàng nhỏ (<1k khách truy cập mỗi ngày), đề xuất của chúng tôi là:

Triển khai một máy chủ - tập tin

Triển khai nhiều máy chủ - Redis (sử dụng cơ sở dữ liệu riêng biệt từ bộ đệm Magento chính)

Tôi đã viết một số câu trả lời thực sự kỹ lưỡng ở đây http://magebase.com/magento-tutorials/magento-session-st Storage-who-to-choose-and-why / comment-page-1 / # com-1980


2
Nếu cron dọn dẹp được cho là để xóa các phiên, tại sao nó không thành công và làm thế nào để khắc phục vấn đề đó thay vì tạo ra một cron mới có cảm giác như một công việc xung quanh?
Ngỗng

12

Tôi đã hỏi một câu hỏi liên quan một thời gian trước đây:

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

Điều tôi chưa bao giờ phát hiện ra (tôi đã bỏ công việc đó cho một người mới và vấn đề ban đầu đã trở thành của người khác) là nếu các phiên của Magento sẽ tôn trọng các cài đặt này hoặc nếu họ thực hiện xử lý phiên của họ bằng Zend (và có lẽ là một loại zend.ini tập tin cấu hình).

Các cài đặt php để xem xét:

session.gc_maxlifetime session.gc_probability session.gc_divisor

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


Tôi rất muốn biết điều này bản thân mình, từ kinh nghiệm của tôi, có vẻ như Magento không tôn trọng các cài đặt này (xem xét các tệp phiên có giá trị GB của GB, sẽ an toàn khi cho rằng tại một thời điểm nào đó, GC sẽ kích hoạt). Vì vậy, tôi chỉ thiết lập kịch bản được đề xuất bởi Ben như một công việc định kỳ để được an toàn.
Javier Villanueva

7

Thông thường một công việc định kỳ là đủ, nhưng đây là một số điều cần lưu ý:

1) Đặt phiên kéo dài không quá session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) giây (điều này sẽ thiết lập các phiên hết hạn để chuẩn bị cho việc thu gom rác bằng php.ini hoặc .htaccess)

2) Bạn có thể muốn lưu trữ các phiên trong cơ sở dữ liệu xem tại đây để biết thêm thông tin về cách thực hiện việc này (tùy chọn này có thể dễ quản lý hơn thông qua mô-đun magento tùy chỉnh)

3) Một lựa chọn khác để xem xét là phù thủy Memcached cũng có thể tăng tốc các máy chủ (mặc dù không hoàn toàn kết nối với câu hỏi, tôi nghĩ rằng nó rất hữu ích để biết về)

Xem câu hỏi này để biết thêm: https://stackoverflow.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept


2
Sử dụng một cronjob để loại bỏ tất cả các tệp phiên là không thể chấp nhận. Điều gì xảy ra khi người dùng thêm nội dung vào giỏ hàng của họ 10 phút trước khi cron chạy? Giỏ hàng của họ bị xóa sạch! Nếu bộ sưu tập rác của PHP không hoạt động, cần phải tìm ra.
davidalger

+1 @davidalger điểm tốt, tôi theo giả định (nhầm lẫn) rằng chỉ các phiên hết hạn đã bị xóa qua cronjob
pzirkind

1
@davidalger - Bộ sưu tập rác của PHP hoạt động thông qua cron. Nó chỉ đơn giản findlà tất cả các tập tin cũ hơn sess.gc_maxlifetimevà loại bỏ chúng. Xóa các phiên thông qua cron là hành vi bình thường, an toàn và chấp nhận được.
Ben Lessani - Sonassi

1
Thật ra, không, không phải vậy. Bộ sưu tập rác phiên được thực hiện khi bắt đầu phiên xảy ra trong quá trình thực thi tập lệnh PHP. Tần suất thu gom rác được chạy tùy thuộc vào giá trị của session.gc_probabilitysession.gc_divisor. Nếu các tập lệnh khác nhau có các giá trị khác nhau cho tập lệnh có giá trị session.gc_maxlifetimethấp nhất sẽ xác định thời gian lưu trữ xung quanh vì bộ lưu trữ phiên là toàn cục và việc thực thi tập lệnh đó sẽ dọn sạch các đối tượng phiên tập lệnh khác.
davidalger

5

Trên tất cả các thiết lập của chúng tôi, chúng tôi có một tệp bảo trì. Việc chăm sóc các bản ghi nhật ký và thư mục var thỉnh thoảng. Vì các phiên phải được lưu trong cơ sở dữ liệu hoặc trên hệ thống tệp, tệp bảo trì này sẽ dọn sạch cả hai. (Xem mã dưới đây).

Bạn có thể chạy lệnh sau dưới dạng công việc định kỳ để dọn sạch các bản ghi:

php maintenance.php clean=log

Lệnh trên sẽ tạo ra đầu ra sau:

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

Bạn có thể chạy lệnh sau dưới dạng công việc định kỳ để dọn sạch thư mục var:

php maintenance.php clean=var

Lệnh trên sẽ tạo ra đầu ra sau:

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

Mã thực tế (Đừng quên điều chỉnh đường dẫn đến tệp local.xml của bạn):

<?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

Đối với Magento CMS và những thứ tương tự (không dọn dẹp các phiên cũ), tôi chỉ sử dụng các công việc định kỳ dựa trên cài đặt php.ini.

PHP5 / Ubuntu 14.04 / Debian

Thiết lập cron.d hệ thống cho php5 không dọn sạch Magento ./var/session (hoặc bất cứ thứ gì ngoài thư mục phiên mặc định (/ var / lib / php5 cho Ubuntu và / var / lib / php5 / session hoặc / tmp / cho hầu hết những người khác Linux xa).

Nhưng bạn vẫn có thể sử dụng "sessionclean" và "maxlifetime" theo cron hệ thống php5 / Debian mặc định:

Ví dụ bạn có thể thử từ dòng lệnh:

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

Vì vậy, chỉ cần kết hợp nó vào một crontab hệ thống / root hoặc một crontab của người dùng có quyền đọc / ghi cho các tệp phiên:

$ sudo crontab -e

Thêm cái này là bạn muốn nó trông giống với hệ thống 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)

hoặc - vì chúng tôi biết những tệp / thư mục đó tồn tại:

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

Bây giờ tôi có số lượng phiên có thể quản lý được và nó được giữ sạch sẽ thông qua bộ sưu tập rác / vòng đời mặc định thông qua cài đặt php.ini (cli).

(Bạn có thể để ký tự đại diện ở trên hoặc thay thế bằng tên trang web.)

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

Tập lệnh 'sessionclean' đã thay đổi và tập lệnh maxlifetime đã bị xóa. Đối với công việc cron hệ thống / php, bây giờ nó là một tập lệnh. Bạn thực sự không thể sử dụng điều này nữa vì các cuộc gọi tệp bây giờ là tĩnh đối với tập lệnh.

Tập lệnh sessionclean php5 cũ hơn vẫn có thể hoạt động cho bạn nếu hệ thống không dọn dẹp. Những gì bạn có thể làm là lấy Gói Debian php5 cũ hơn và trích xuất sessioncleantừ nó. Hoặc bạn chỉ có thể sao chép phần này vào vùng tập lệnh của mình (cung cấp quyền / quyền sở hữu / var / www / (trang web) phù hợp):

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

Tôi cũng khuyên bạn nên đổi tên nó, vì vậy nó không bị nhầm lẫn với cronjob php 'sessionclean' mới. Sau đó, bạn có thể cắm số "maxlifetime" của riêng mình vào như vậy:

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

(61 là tuổi mẫu (tính bằng phút) và 'MySessionClean' là tập lệnh php5 được đổi tên được tải xuống hoặc sao chép từ trên xuống).

Theo cách này, chúng tôi tránh hoàn toàn các cuộc gọi php.ini / env.

(EDIT 13DEC2016: Cập nhật LIÊN KẾT REPBIAN ARCHIVE)


3

Tôi đã xóa DB một cách thường xuyên khỏi tất cả các tệp phiên cũ này. Thật khó chịu khi làm việc thủ công cho đến khi tôi cài đặt Trình tối ưu hóa Magento , điều này làm cho tất cả công việc thường ngày này hoạt động với tôi. Ngoài ra, bộ nhớ cache của tôi được làm mới liên tục và tôi không làm thủ công sau khi thay đổi sản phẩm và khối tĩnh. Ồ, vâng, báo cáo lỗi và giỏ hàng bị bỏ rơi cũng được làm sạch.


3

Trong tất cả các Nhận xét ở trên, tôi nghĩ rằng đây là giải pháp dễ dàng và hy vọng nó tốt hơn các tập lệnh dài và cài đặt tiện ích mở rộng của bên thứ 3 để quản lý các tệp phiên cũ và giữ các tệp phiên mới.

  1. Tạo một tên tệp "clean_session.sh" trong magentothư mục của bạn .
  2. Dán những dòng này.

#!/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. Sau đó, bạn có thể lên lịch cronjob hàng tuần để thực hiện dọn dẹp.

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

  1. Đừng quên làm cho tập tin thực thi như

chmod u+x clean_session.sh

  1. Và bạn cũng có thể chạy nó như

sh clean_session.sh


3

Đối với trường hợp của tôi, tôi chạy tập lệnh này được đặt trong magento/var/thư mục để xóa các tệp phiên hơn một tuần ( -mtime +7) cũ:

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

Đó là tập lệnh bash đầu tiên của tôi (phiên bản 2) và tôi nghĩ nó có thể được tối ưu hóa ở một số khía cạnh. Tôi đang mở cho bất kỳ đề xuất tối ưu hóa.

Tập lệnh này có thể được truy xuất tại: https://gist.github.com/Nolwennig/a75dc2f8628be2864bb2


0

Tôi đã tạo một tập lệnh làm trống thư mục var / session. Bạn có thể thêm nó vào một công việc định kỳ để chạy một lần mỗi ngày, điều đó là đủ và điều chỉnh khi cần thiết. Bạn sẽ nhận thấy khi thư mục phiên của bạn được điền, không thể xóa các tệp qua cpanel hoặc ssh, tập lệnh này sẽ thực hiện thủ thuật chỉ cần đặt trong thư mục gốc 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);

Vấn đề với kịch bản này là nó xóa tất cả các phiên, không chỉ các phiên cũ. Vì vậy, không ai có thể đăng nhập lâu hơn một ngày (nếu bạn chạy hàng ngày này) và tất cả các giỏ hàng sẽ trống sau khi chạy xong (vì vậy không có giỏ hàng nào giữ được lâu hơn một ngày).
simonthesorcerer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.