Il problema è causato da un blocco inserito dal gestore della sessione PHP. Quindi Magento non sta bloccando esplicitamente qualcosa e sta provando a bloccare le richieste di amministrazione, ma quasi un effetto di per sé dello storage di sessione basato su file.
Un blocco di scrittura viene posta sul file di dati di sessione quando viene aperto dal (annoso) richiesta iniziale, causando la seconda richiesta di blocco fino a quando il blocco viene rilasciato quando chiama session_start
inMage_Core_Model_Session_Abstract_Varien::start
Questo è riproducibile al 100%. Ho usato lo stesso metodo che hai fatto, aggiungendo a sleep(30)
all'inizioMage_Adminhtml_IndexController::globalSearchAction
Vale la pena notare che questo non può essere riprodotto se si utilizza l'archiviazione di sessioni db. Dopo aver trovato la causa principale, ho impostato un sandbox per l'archiviazione della sessione db e non sono più riuscito a riprodurre il problema. Quindi i gestori di sessioni db Magento sembra non usare il blocco a livello di riga per bloccare le scritture di sessioni. Lo trovo interessante, perché ha il potenziale per la perdita di dati di sessione poiché l'applicazione ovviamente non tiene conto di più thread che scrivono nella stessa sessione. Nota per i lettori: non userei mai l'archiviazione di sessioni db in produzione per provare a risolvere questo problema, è utile solo per sovraccaricare il database MySql.
Non ho provato a riprodurre il comportamento utilizzando sistemi di archiviazione di sessioni basati sulla memoria come Redis, ma la mia ipotesi è che il blocco dei record nell'archivio sessioni sia stato probabilmente trascurato anche in questi.
Esistono tecniche che potrebbero essere impiegate per evitarlo, come utilizzare session_write_close
per rilasciare il blocco prima di iniziare un lavoro di lunga durata. Ma questo ti impedirebbe anche di scrivere alla sessione poiché l'hai appena chiusa. Quindi non è probabile che venga implementato facilmente su tutta la linea in Magento, ma potrebbe potenzialmente essere implementato su route / controller specifici.
La mia tecnica per bloccare questo come causa principale era di abilitare il profiler Xdebug ed esaminare il file "cachegrind". Una volta completata la seconda richiesta, ho caricato il file di output (~ 25 MB di registro) in MacCallGrind e ho eseguito il drill-down nella traccia seguendo il percorso delle chiamate in cui il tempo compreso era di almeno 28 secondi. Questo alla fine mi ha portato alla session_start
chiamata che ha richiesto circa 28 secondi per essere eseguito, dandomi un ottimo punto di ricerca.
EDIT: Per gli interessati, ho pubblicato uno screenshot del file "cachegrind" visualizzato in MacCallGrind su Twitter.