Richieste di pagine amministrative di lunga durata che bloccano altre richieste


17

Se ho effettuato l'accesso al back-end di Magento ed eseguo attività che richiedono molto tempo (ricerca globale su cataloghi di grandi dimensioni, flusso di dati di lunga durata, ecc.), Il mio browser Web rifiuterà di caricare altre pagine di amministrazione solo in quel browser . Perché questo accade e c'è qualche scienza nota per soluzioni alternative?

Cioè, se io

  1. Accedi alla pagina del dashboard di Magento

  2. Apri una seconda scheda con qualsiasi pagina di amministrazione Magento

  3. Eseguire una ricerca globale di lunga durata (simulata con una chiamata sleep(30)all'inizio globalSearchAction) nella prima scheda

  4. Tentativo di ricaricare la seconda scheda

Comportamento previsto: la seconda scheda viene caricata immediatamente con il contenuto della pagina

Comportamento effettivo: la seconda scheda viene caricata solo al termine della ricerca globale di lunga durata

Qualcuno sa, in particolare, perché questo accade? (Suppongo che le richieste della console di amministrazione di Magento blocchino alcune risorse che Magento deve avviare, ma non so di cosa si tratta)

Qualcuno sa di una correzione / soluzione?


1
Lei, signore, mi ha appena inviato una sfida! :)
davidalger,

Risposte:


21

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_startinMage_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_closeper 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_startchiamata 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.


Il modulo uRapidFlow di Unirgy chiude la sessione per evitare questo problema, il che è bello in un certo senso, ma è frustrante in quanto rende difficile fornire un feedback all'utente in seguito.
Peter O'Callaghan,

@davidalger - Con quale spazio di archiviazione di solito distribuisci per i siti client?
Alan Storm,

3
Ri: blocco del file di sessione PHP, questo è meno per l'integrità dei dati che per l'integrità del file su disco stesso. Avere più processi che si aprono e scrivono su bit su disco (che è un file) porterà rapidamente alla corruzione dei dati. MySQL, redis e la maggior parte dei database sono progettati specificamente per rimanere coerenti, anche se ci sono più scritture contemporaneamente. cioè non è che il blocco è stato trascurato, è che non è così critico.
Alan Storm,

@AlanStorm - Un'istanza Memcached dedicata per un'installazione con bilanciamento del carico, file system per cluster di nodi a singola applicazione. Il file system funziona meglio se non hai più nodi poiché non hai latenza IP.
davidalger,

Corretto, bloccare il file significa prevenire la corruzione dei dati. Tuttavia, tenere premuto il blocco fino alla chiusura della sessione significa prevenire la perdita di dati. Se due processi caricano i dati della sessione, li modificano e poi li scrivono, uno di essi avrà le sue sovrascritture. Generalmente non costituirà un problema critico, ma potrebbe causare la perdita di dati e / o problemi difficili da debug.
davidalger,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.