Jika saya masuk ke backend Magento dan melakukan beberapa tugas yang membutuhkan waktu lama (pencarian global pada katalog besar, aliran data yang berjalan lama, dll), browser web saya akan menolak untuk memuat halaman admin lain di browser itu saja . Mengapa ini terjadi, dan adakah ilmu yang diketahui untuk mengatasi masalah?
Itu kalau saya
Masuk ke halaman dasbor Magento
Buka tab kedua dengan halaman admin Magento
Lakukan pencarian global yang berjalan lama (disimulasikan dengan panggilan
sleep(30)
di awalglobalSearchAction
) di tab pertamaCoba muat ulang tab kedua
Perilaku yang Diharapkan: Tab kedua langsung memuat konten halaman
Perilaku Aktual: Tab kedua hanya dimuat setelah pencarian global yang berjalan lama selesai
Adakah yang tahu, secara khusus, mengapa ini terjadi? (Tebakan saya adalah permintaan konsol admin Magento mengunci beberapa sumber daya Magento perlu bootstrap, tapi saya tidak tahu apa itu)
Apakah ada yang tahu tentang perbaikan / penyelesaian masalah?
sumber
Jawaban:
Masalahnya disebabkan oleh kunci yang ditempatkan oleh pengendali sesi PHP. Jadi bukan Magento yang secara eksplisit mengunci sesuatu dan mencoba memblokir permintaan admin, tetapi hampir efek samping per-se penyimpanan sesi berbasis file.
Kunci write sedang ditempatkan pada file data sesi bila dibuka oleh awal (lama berjalan) permintaan, menyebabkan permintaan kedua untuk blok sampai mengunci dilepaskan ketika panggilan
session_start
diMage_Core_Model_Session_Abstract_Varien::start
Ini 100% dapat direproduksi. Saya menggunakan metode yang sama yang Anda lakukan, menambahkan
sleep(30)
ke atasMage_Adminhtml_IndexController::globalSearchAction
Perlu dicatat adalah bahwa ini tidak dapat direproduksi jika Anda menggunakan penyimpanan sesi db. Setelah saya menemukan akar penyebabnya, saya mengatur kotak pasir ke penyimpanan sesi db dan tidak bisa lagi mereproduksi masalah. Jadi pengendali sesi db Magento tampaknya tidak menggunakan penguncian tingkat baris untuk mengunci sesi menulis. Saya menemukan ini menarik, karena memiliki potensi kehilangan data sesi karena aplikasi ini jelas tidak memperhitungkan beberapa utas menulis ke sesi yang sama. Catatan untuk Pembaca: Saya tidak akan pernah menggunakan penyimpanan sesi db dalam produksi untuk mencoba dan menyelesaikan ini, itu hanya baik untuk membebani database MySql Anda.
Saya tidak mencoba mereproduksi perilaku menggunakan sistem penyimpanan sesi berbasis memori seperti Redis, tetapi tebakan saya adalah bahwa mengunci catatan di toko sesi mungkin diabaikan dalam hal ini juga.
Ada beberapa teknik yang bisa digunakan untuk menghindari hal ini seperti menggunakan
session_write_close
untuk melepaskan kunci sebelum Anda memulai pekerjaan yang sudah berjalan lama. Tetapi ini juga akan mencegah Anda dari menulis ke sesi karena Anda baru saja menutupnya. Jadi sepertinya tidak akan mudah diimplementasikan di seluruh papan di Magento, tetapi berpotensi dapat diimplementasikan pada rute / pengendali tertentu.Teknik saya untuk menyematkan ini sebagai penyebab utama adalah mengaktifkan Xdebug profiler dan memeriksa file "cachegrind". Setelah permintaan kedua selesai, saya memuat file output (~ 25 MB log) ke MacCallGrind dan menelusuri jejak yang mengikuti jejak panggilan di mana waktu inklusif adalah 28 detik atau lebih besar. Ini akhirnya membawa saya ke
session_start
panggilan yang membutuhkan waktu ~ 28 detik untuk berjalan, memberi saya poin yang bagus untuk penelitian.EDIT: Bagi yang berminat, saya telah memposting tangkapan layar file "cachegrind" yang dilihat di MacCallGrind di Twitter.
sumber