Wenn ich im Backend von Magento angemeldet bin und eine Aufgabe ausführe, die lange dauert (globale Suche in großen Katalogen, Datenfluss usw.), lehnt mein Webbrowser das Laden anderer Verwaltungsseiten nur in diesem Browser ab . Warum passiert das und gibt es eine bekannte Wissenschaft für Problemumgehungen?
Das ist, wenn ich
Melden Sie sich auf der Dashboard-Seite von Magento an
Öffnen Sie eine zweite Registerkarte mit einer beliebigen Magento-Administrationsseite
Führen Sie auf der ersten Registerkarte eine globale Suche mit langer Laufzeit durch (simuliert mit einem Aufruf von
sleep(30)
zu BeginnglobalSearchAction
)Versuchen Sie, die zweite Registerkarte neu zu laden
Erwartetes Verhalten: Die zweite Registerkarte wird sofort mit dem Seiteninhalt geladen
Tatsächliches Verhalten: Die zweite Registerkarte wird erst geladen, wenn die lange laufende globale Suche abgeschlossen ist
Weiß jemand konkret, warum das passiert? (Ich vermute, dass Magento-Administratorkonsolenanforderungen eine Ressource sperren, die Magento zum Booten benötigt, aber ich weiß nicht, was das ist.)
Kennt jemand einen Fix / Workaround?
quelle
Antworten:
Das Problem wird durch eine Sperre des PHP-Session-Handlers verursacht. Es ist also nicht Magento, das explizit etwas sperrt und versucht, Administratoranforderungen zu blockieren, sondern fast ein Nebeneffekt des dateibasierten Sitzungsspeichers.
Eine Schreibsperre wird auf der Sitzungsdaten - Datei platziert , wenn es von der anfänglichen (Langlauf) Anforderung geöffnet wird, wodurch die zweite Anfrage nach Block , bis die Sperre gelöst wird , wenn es ruft
session_start
inMage_Core_Model_Session_Abstract_Varien::start
Dies ist zu 100% reproduzierbar. Ich habe die gleiche Methode angewendet, die Sie angewendet haben, indem ich
sleep(30)
oben ein hinzugefügt habeMage_Adminhtml_IndexController::globalSearchAction
Beachten Sie, dass dies nicht reproduziert werden kann, wenn Sie den Datenbanksitzungsspeicher verwenden. Nachdem ich die Hauptursache gefunden hatte, stellte ich eine Sandbox auf Datenbanksitzungsspeicher ein und konnte das Problem nicht mehr reproduzieren. Die Datenbank-Session-Handler von Magento verwenden anscheinend keine Sperren auf Zeilenebene, um Session-Schreibvorgänge zu sperren. Ich finde das interessant, weil es das Potenzial für Sitzungsdatenverlust gibt, da die Anwendung offensichtlich nicht für mehrere Threads verantwortlich ist, die in dieselbe Sitzung schreiben. Hinweis für Leser: Ich würde in der Produktion niemals db session storage verwenden, um dieses Problem zu lösen. Es ist nur gut, um Ihre MySql-Datenbank zu überlasten.
Ich habe nicht versucht, das Verhalten mit speicherbasierten Sitzungsspeichersystemen wie Redis zu reproduzieren, aber ich vermute, dass das Sperren der Datensätze im Sitzungsspeicher wahrscheinlich auch hier übersehen wurde.
Es gibt Techniken, mit denen dies vermieden werden kann, z. B.
session_write_close
das Aufheben der Sperre, bevor Sie einen langfristigen Auftrag ausführen. Dies würde Sie jedoch auch daran hindern, an die Sitzung zu schreiben, da Sie sie gerade geschlossen haben. Es ist daher nicht sehr wahrscheinlich, dass es in Magento allgemein implementiert werden kann, aber es kann möglicherweise auf bestimmten Routen / Controllern implementiert werden.Meine Technik, um dies als Grundursache festzuhalten, bestand darin, den Xdebug-Profiler zu aktivieren und die "Cachegrind" -Datei zu untersuchen. Sobald die zweite Anforderung abgeschlossen war, lud ich die Ausgabedatei (ca. 25 MB Protokoll) in MacCallGrind und führte einen Drilldown in die Ablaufverfolgung auf dem Pfad der Aufrufe durch, bei denen die Einschlusszeit 28 Sekunden oder mehr betrug. Dies führte mich schließlich zu dem
session_start
Anruf, dessen Ausführung ~ 28 Sekunden in Anspruch nahm, und gab mir einen großartigen Anhaltspunkt für die Recherche von.BEARBEITEN: Für die Interessierten habe ich einen Screenshot der "Cachegrind" -Datei gepostet, die in MacCallGrind auf Twitter angezeigt wird.
quelle