Si je suis connecté au backend de Magento et que j'effectue une tâche qui prend beaucoup de temps (recherche globale sur de gros catalogues, flux de données long, etc.), mon navigateur Web refusera de charger d'autres pages d'administration dans ce navigateur uniquement . Pourquoi cela se produit-il et existe-t-il une science connue pour des solutions de contournement?
Autrement dit, si je
Connectez-vous à la page du tableau de bord de Magento
Ouvrez un deuxième onglet avec n'importe quelle page d'administration Magento
Effectuez une recherche globale de longue durée (simulée avec un appel à
sleep(30)
au début deglobalSearchAction
) dans le premier ongletEssayez de recharger le deuxième onglet
Comportement attendu: le deuxième onglet se charge immédiatement avec le contenu de la page
Comportement réel: le deuxième onglet ne se charge qu'une fois la recherche globale de longue durée terminée
Quelqu'un sait-il précisément pourquoi cela se produit? (Je suppose que les demandes de la console d'administration Magento verrouillent certaines ressources dont Magento a besoin pour démarrer, mais je ne sais pas ce que c'est)
Quelqu'un connaît-il un correctif / une solution de contournement?
la source
Réponses:
Le problème est dû à un verrou placé par le gestionnaire de session PHP. Ce n'est donc pas Magento verrouillant explicitement quelque chose et essayant de bloquer les demandes d'administration, mais presque un effet secondaire en soi du stockage de session basé sur des fichiers.
Un verrou d'écriture est placé sur le fichier de données de session lors de son ouverture par la demande initiale ( de longue durée), ce qui provoque la deuxième demande de blocage jusqu'à ce que le verrou est libéré quand il appelle
session_start
àMage_Core_Model_Session_Abstract_Varien::start
Ceci est 100% reproductible. J'ai utilisé la même méthode que vous, en ajoutant un
sleep(30)
en haut deMage_Adminhtml_IndexController::globalSearchAction
Il convient de noter que cela ne peut pas être reproduit si vous utilisez le stockage de session db. Après avoir trouvé la cause première, j'ai défini un sandbox sur le stockage de session db et je ne pouvais plus reproduire le problème. Ainsi, les gestionnaires de sessions db Magento n'ont apparemment pas utilisé de verrouillage au niveau des lignes pour verrouiller les écritures de session. Je trouve cela intéressant, car il a le potentiel de perte de données de session car l'application ne prend évidemment pas en compte plusieurs threads écrivant dans la même session. Remarque pour les lecteurs: je n'utiliserais jamais le stockage de session db en production pour essayer de résoudre ce problème, c'est seulement bon pour surcharger votre base de données MySql.
Je n'ai pas essayé de reproduire le comportement à l'aide de systèmes de stockage de session basés sur la mémoire tels que Redis, mais je suppose que le verrouillage des enregistrements dans le magasin de sessions a probablement été également ignoré dans ces derniers.
Il existe des techniques qui peuvent être utilisées pour éviter cela, comme utiliser
session_write_close
pour libérer le verrou avant de commencer un travail de longue durée. Mais cela vous empêcherait également d'écrire à la session puisque vous venez de la fermer. Il est donc peu probable qu'il soit facilement implémenté dans Magento, mais pourrait potentiellement être implémenté sur des routes / contrôleurs spécifiques.Ma technique pour épingler cela comme cause principale était d'activer le profileur Xdebug et d'examiner le fichier "cachegrind". Une fois la deuxième demande terminée, j'ai chargé le fichier de sortie (~ 25 Mo de journal) dans MacCallGrind et exploré la trace en suivant le chemin des appels où le temps inclus était de 28 secondes ou plus. Cela m'a finalement conduit à l'
session_start
appel qui a duré environ 28 secondes, ce qui m'a donné un excellent point de recherche.EDIT: Pour les intéressés, j'ai posté une capture d' écran du fichier "cachegrind" affiché dans MacCallGrind sur Twitter.
la source