Permintaan Halaman Admin Berjalan Lama Memblokir Permintaan Lainnya

17

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

  1. Masuk ke halaman dasbor Magento

  2. Buka tab kedua dengan halaman admin Magento

  3. Lakukan pencarian global yang berjalan lama (disimulasikan dengan panggilan sleep(30)di awal globalSearchAction) di tab pertama

  4. Coba 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?

Alan Storm
sumber
1
Anda, Tuan, baru saja mengirim saya ke sebuah tantangan! :)
davidalger

Jawaban:

21

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_startdiMage_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_closeuntuk 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_startpanggilan 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.

davidalger
sumber
Modul uRapidFlow dari Unirgy menutup sesi untuk menghindari masalah ini, yang memang bagus, tetapi hal ini membuat frustasi karena membuatnya sulit untuk memberikan umpan balik kepada pengguna sesudahnya.
Peter O'Callaghan
@davidalger - Penyimpanan sesi apa yang biasanya Anda gunakan untuk situs klien?
Alan Storm
3
Re: mengunci file sesi PHP, ini kurang untuk integritas data daripada integritas file pada disk itu sendiri. Memiliki banyak proses membuka dan menulis ke bit pada disk (yang merupakan file) dengan cepat akan menyebabkan kerusakan data. MySQL, redis, dan kebanyakan basis data dirancang khusus untuk tetap konsisten, bahkan jika ada beberapa penulisan pada waktu yang hampir bersamaan. yaitu bukan bahwa penguncian diabaikan, itu tidak dibutuhkan secara kritis.
Alan Storm
@AlanStorm - Sebuah instance Memcached yang berdedikasi untuk instalasi yang seimbang, sistem file untuk cluster node aplikasi tunggal. Sistem file berkinerja terbaik di mana Anda tidak memiliki banyak node karena Anda tidak memiliki latensi IP.
davidalger
Benar, mengunci file adalah tentang mencegah kerusakan data. Namun, memegang kunci sampai sesi ditutup adalah tentang mencegah kehilangan data. Jika dua proses memuat data sesi, memodifikasinya dan kemudian menuliskannya, salah satunya akan ditimpa modifikasi. Secara umum tidak akan menimbulkan masalah kritis, tetapi dapat menyebabkan kehilangan data dan / atau sulit untuk men-debug masalah.
davidalger