Bagaimana saya harus menangani file sesi yang terlalu banyak?

43

Saya bertindak sebagai sysadmin untuk beberapa server yang menyimpan situs Magento dan terkadang mereka mengisi dengan file sesi.

Saya telah diberitahu bahwa mengelola file-file ini bukan sesuatu yang dapat dilakukan dari dalam Magento dan saya menganggap penggunaan sementara mereka berarti mereka tidak dapat dimatikan begitu saja, tetapi tampaknya aneh bahwa Magento tidak memiliki cara untuk menangani penghapusan ini file?

Solusi saya adalah crontab malam hari yang melakukan sesuatu seperti ini find /path/to/magento/sessions/ -name "sess*" -type f -deletetetapi rasanya tidak bisa dikatakan.

Apa cara terbaik untuk menangani ini?

Toby
sumber

Jawaban:

37

Selain menghapus file sesi dengan findmenggunakan waktu modifikasi khusus seperti yang disebutkan oleh orang lain, Anda juga dapat:

  • Simpan sesi di basis data Anda . Tentu saja ini akan menempatkan beban pada basis data Anda dan itu bukan cara tercepat, tetapi Anda dapat menangani lebih banyak sesi dengan cara itu dan Anda dapat berbagi sesi antara beberapa server frontend. Anda dapat mengubah pengaturan app/etc/local.xmldengan beralih

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

    untuk

    <session_save><![CDATA[db]]></session_save>
  • Gunakan memcached sebagai penyimpanan sesi Anda. Magento juga mendukung ini secara default. Lihat app/etc/local.xml.additionaluntuk konfigurasi. Saya tidak pernah menggunakannya dalam produksi tetapi telah mendengar bahwa ini mungkin sedikit rumit.

  • Menangani sesi di Redis menggunakan Cm_RedisSession ekstensi cerdas Colin Mollenhours . Menyiapkan Redis seharusnya tidak memakan waktu terlalu lama, juga dapat digunakan untuk caching (lihat Cm_Cache_Backend_Redis ) dan menggabungkan cache RAM dengan ketekunan pada disk (bertentangan dengan memcached, disk RAM atau sejenisnya) yang selalu dalam kasus server Anda menabrak

Matthias Zeis
sumber
1
Menyimpan sesi dalam database juga lebih aman. Jika file .htaccess Anda tidak ada di sana (karena seseorang menghapus folder var), file sesi Anda tidak akan dapat diakses dari luar.
Erfan
8
Menyimpan sesi dalam database adalah A Bad Idea. Itu tidak dirancang untuk tujuan itu dan MySQL berfungsi sebagai alat yang sangat buruk untuk penyimpanan sesi, mengunci menjadi masalah utama - belum lagi tidak ada dukungan bawaan untuk pembersihan.
Ben Lessani - Sonassi
28

Dengan sesi berbasis file, mereka akan dipangkas secara otomatis oleh cron pembersihan sesi PHP - sehingga file-file tersebut kemungkinan akan dihapus dalam ~ 7200 detik penciptaan. Jadi, bahkan di situs yang sibuk (30 ribu uniques per hari), biasanya hanya ada sekitar 4.000 file sesi di ./var/session - yang bahkan tidak ada artinya untuk server Linux kelas bawah.

Namun, pembersihan sebenarnya bergantung pada kerja cron - yang biasanya tidak terlihat di direktori ./var/session dari Magento. Jadi, Anda harus mengatur cron sistem baru

/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

Periode pembersihan default untuk sesi adalah 7200 detik, yang seharusnya lebih dari cukup, meskipun Anda dapat mengubah yang di atas sesuai.

Dengan sesi Memcache, TCP / IP adalah satu-satunya overhead - yang untuk penyebaran server tunggal, akan membuatnya lebih lambat daripada berbasis file. Jadi, Anda akan menggunakan soket unix sebagai gantinya, yang menghapus overhead itu dan memberikan keamanan yang lebih baik. Tetapi meskipun begitu, sesi pelanggan Anda akan dipotong / dibatasi untuk jumlah RAM yang dapat Anda alokasikan. Sesi Magento rata-rata adalah 4Kb - sehingga Anda dapat mendukung 256 sesi aktif, per MB yang Anda alokasikan. Jadi pastikan untuk menetapkan batas yang sesuai untuk menghindari pelanggan kehilangan keranjang / sesi secara acak. Dan juga perlu diingat, daemon Memcache restart akan menghapus semua sesi yang ada (BAD!).

Dengan Redis (bukan asli, tetapi tersedia melalui ekstensi), Anda mendapatkan tingkat dukungan yang sama seperti Memcache, tetapi dengan manfaat tambahan dari kegigihan (jika Anda ingin menggunakannya). Dengan ekstensi Cm_Redis, Anda juga dapat memanfaatkan kompresi sesi. Kami telah menemukan ekstensi ini bekerja dengan sangat baik pada penerapan CE dan EE.

Dengan DB, pengaturan kadaluwarsa prune default adalah 1 minggu yang perkasa, jadi dengan ukuran toko di atas sebagai contoh (30k uniques per hari), Anda akan melihat ukuran tabel DB untuk core_cache_session sekitar 7GB - yang akan menggiling toko Anda berhenti total, untuk hampir setiap operasi berbasis sesi.

Dari pengalaman hosting toko besar (230rb pengunjung unik per hari) dan kecil (<1rb pengunjung unik per hari), rekomendasi kami adalah:

Penempatan server tunggal - file

Penempatan multi-server - Redis (menggunakan database terpisah dari cache Magento utama)

Saya menulis beberapa balasan yang sangat teliti di sini http://magebase.com/magento-tutorials/magento-session-storage-which-to-choose-and-why/comment-page-1/#comment-1980

Ben Lessani - Sonassi
sumber
2
Jika cron pembersihan seharusnya menghapus sesi, mengapa gagal, dan bagaimana masalah itu bisa diatasi alih-alih membuat cron baru yang terasa seperti bekerja di sekitar?
Angsa
12

Saya telah mengajukan pertanyaan terkait beberapa waktu lalu:

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

Apa yang tidak pernah saya temukan (saya meninggalkan pekerjaan itu untuk yang baru, dan masalah asli menjadi milik orang lain) adalah jika sesi Magento akan menghormati pengaturan ini, atau jika mereka menerapkan penanganan sesi mereka menggunakan Zend (dan mungkin semacam zend.ini file konfigurasi).

Pengaturan php untuk melihat:

session.gc_maxlifetime session.gc_probability session.gc_divisor

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

pspahn
sumber
Saya ingin mengetahui hal ini sendiri, dari pengalaman saya sepertinya Magento tidak menghormati pengaturan ini (mengingat saya memiliki nilai GB file sesi yang aman, akan aman untuk mengasumsikan bahwa pada titik tertentu GC akan dipicu). Jadi saya hanya mengatur skrip yang direkomendasikan oleh Ben sebagai pekerjaan cron agar aman.
Javier Villanueva
7

Biasanya pekerjaan cron sudah mencukupi, tetapi berikut adalah beberapa hal yang perlu diingat:

1) Setel sesi agar tidak lebih dari session.gc_maxlifetime( php -i | grep session.gc_maxlifetime) detik (ini akan mengatur sesi yang sudah kadaluwarsa untuk dipersiapkan untuk pengumpulan sampah oleh php.ini atau .htaccess)

2) Anda mungkin ingin menyimpan sesi dalam database lihat di sini untuk info lebih lanjut tentang cara melakukan ini (opsi ini mungkin lebih mudah dikelola melalui modul magento khusus)

3) Pilihan lain untuk dipertimbangkan adalah penyihir Memcached juga dapat mempercepat server (meskipun tidak sepenuhnya terhubung ke pertanyaan, saya pikir itu berguna untuk diketahui)

Lihat pertanyaan ini untuk info lebih lanjut: https://stackoverflow.com/questions/4353875/how-long-do-the-magento-session-files-need-to-be-kept

pzirkind
sumber
2
Menggunakan cronjob untuk menghapus semua file sesi tidak dapat diterima. Apa yang terjadi ketika pengguna menambahkan barang ke troli mereka 10 menit sebelum cron berjalan? Gerobak mereka dibersihkan! Jika pengumpulan sampah PHP tidak berfungsi, itu perlu dipecahkan.
davidalger
+1 @davidalger poin bagus, saya berada di bawah asumsi (salah) bahwa hanya sesi yang kadaluarsa yang dihapus melalui cronjob
pzirkind
1
@davidalger - Pengumpulan sampah PHP sendiri beroperasi melalui cron. Itu hanya findsemua file yang lebih tua dari sess.gc_maxlifetimedan menghapusnya. Menghapus sesi melalui cron adalah perilaku yang normal, aman dan dapat diterima.
Ben Lessani - Sonassi
1
Sebenarnya tidak. Pengumpulan sampah sesi dilakukan ketika sesi mulai terjadi selama eksekusi skrip PHP. Seberapa sering pengumpulan sampah dijalankan tergantung pada nilai session.gc_probabilitydan session.gc_divisor. Jika skrip yang berbeda memiliki nilai yang berbeda untuk skrip session.gc_maxlifetimedengan nilai terendah akan menentukan berapa lama barang bertahan sejak penyimpanan sesi bersifat global dan eksekusi skrip tersebut akan membersihkan objek sesi skrip lainnya.
davidalger
5

Pada semua pengaturan kami, kami memiliki file maintenance.php yang menangani pembersihan log dan direktori var sesekali. Karena sesi harus disimpan dalam database atau pada sistem file, file pemeliharaan ini akan membersihkan keduanya. (Lihat kode di bawah).

Anda dapat menjalankan perintah berikut sebagai tugas cron untuk membersihkan log:

php maintenance.php clean=log

Perintah di atas akan menghasilkan output berikut:

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

Anda dapat menjalankan perintah berikut sebagai tugas cron untuk membersihkan folder var:

php maintenance.php clean=var

Perintah di atas akan menghasilkan output berikut:

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

Kode aktual (Jangan lupa untuk menyesuaikan jalur ke file local.xml Anda):

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

Untuk Magento CMS dan sejenisnya (yang tidak membersihkan sesi lama), saya hanya menggunakan pekerjaan cron berdasarkan pengaturan php.ini.

PHP5 / Ubuntu 14.04 / Debian

Pengaturan cron.d sistem untuk php5 tidak membersihkan Magento ./var/session (atau apa pun selain folder sesi default (/ var / lib / php5 untuk Ubuntu dan / var / lib / php5 / sesi atau / tmp / untuk kebanyakan Linux lainnya) dists).

Tetapi Anda masih dapat menggunakan "sessionclean" dan "maxlifetime" sesuai dengan cron sistem php5 / Debian default:

Contoh Anda dapat mencoba dari baris Perintah:

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

Jadi masukkan saja itu ke dalam sistem / root crontab atau crontab pengguna yang memiliki izin baca / tulis untuk file sesi:

$ sudo crontab -e

Tambahkan ini, Anda ingin tampilannya mirip dengan sistem 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)

atau - karena kita tahu file / dir itu ada:

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

Sekarang saya memiliki sejumlah sesi yang dapat dikelola dan tetap bersih melalui pengumpulan sampah / masa pakai default melalui pengaturan php.ini (cli).

(Anda dapat meninggalkan wildcard di atas atau mengganti dengan sitename.)

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

Script 'sessionclean' telah berubah dan script maxlifetime telah dihapus. Untuk pekerjaan sistem / php cron sekarang menjadi satu skrip. Anda tidak dapat benar-benar menggunakan ini lagi karena panggilan file sekarang statis ke skrip.

Script sessionclean php5 yang lebih lama masih dapat bekerja untuk Anda jika sistem tidak membersihkan. Yang bisa Anda lakukan adalah mengambil Paket php5 Debian yang lebih lama dan mengekstraknya sessionclean. Atau Anda cukup menyalin ini ke area skrip Anda (memberikan izin / kepemilikan / var / www / (situs) yang tepat):

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

Saya juga merekomendasikan untuk mengganti nama itu, jadi itu tidak bingung dengan cronjob php 'sessionclean' baru. Anda kemudian dapat memasukkan nomor "maxlifetime" sendiri seperti:

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

(61 menjadi contoh usia (dalam menit) dan 'MySessionClean' menjadi skrip php5 yang diganti nama diunduh atau disalin dari atas).

Dengan cara ini kami menghindari panggilan php.ini / env sepenuhnya.

(EDIT 13DEC2016: Diperbarui DEBIAN ARCHIVE REPO LINK)

bshea
sumber
3

Saya membersihkan DB secara teratur dari semua file sesi lama ini. Itu adalah pekerjaan manual yang menjengkelkan sampai saya menginstal Magento Optimizer yang membuat semua pekerjaan rutin ini bagi saya. Juga, cache saya di-refresh terus-menerus dan saya tidak melakukannya secara manual setelah mengubah produk dan blok statis. Oh, ya, laporan kesalahan dan gerobak terlantar juga dibersihkan.

James
sumber
3

Dari semua Komentar di atas, saya pikir ini adalah solusi yang mudah dan berharap ini lebih baik daripada skrip panjang dan menginstal ekstensi pihak ke-3 untuk mengelola file sesi lama dan menyimpan file sesi baru.

  1. Buat nama file "clean_session.sh" di bawah magentofolder Anda .
  2. Tempel garis ini.

#!/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. Kemudian Anda dapat menjadwalkan cronjob mingguan untuk melakukan pembersihan.

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

  1. Jangan lupa untuk membuat file tersebut dapat dieksekusi sebagai

chmod u+x clean_session.sh

  1. Dan Anda juga dapat menjalankannya sebagai

sh clean_session.sh

Anil
sumber
3

Untuk kasus saya, saya menjalankan skrip ini ditempatkan di magento/var/direktori untuk menghapus file sesi lebih dari satu minggu ( -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

Ini skrip bash pertama saya (revisi 2) dan saya pikir ini dapat dioptimalkan dalam beberapa aspek. Saya terbuka untuk saran pengoptimalan apa pun.

Script ini dapat diambil di: https://gist.github.com/Nolwennig/a75dc2f8628be2864bb2

Nolwennig
sumber
0

Saya membuat skrip yang mengosongkan direktori var / session. Anda dapat menambahkannya ke tugas cron untuk dijalankan sekali per hari yang seharusnya cukup dan sesuaikan sesuai kebutuhan. Anda akan melihat ketika direktori sesi Anda terisi, tidak mungkin untuk menghapus file melalui cpanel atau ssh, skrip ini akan melakukan triknya hanya menempatkan di direktori root 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);
Lawrence Farbman
sumber
Masalah dengan skrip ini adalah ia menghapus semua sesi, bukan hanya yang lama. Jadi tidak ada yang bisa login lebih dari satu hari (jika Anda menjalankan ini setiap hari), dan semua kereta akan kosong setelah ini berjalan (jadi tidak ada kereta yang bisa tahan lebih dari satu hari).
simonthesorcerer