Demandes de page d'administration de longue durée Blocage d'autres demandes


17

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

  1. Connectez-vous à la page du tableau de bord de Magento

  2. Ouvrez un deuxième onglet avec n'importe quelle page d'administration Magento

  3. Effectuez une recherche globale de longue durée (simulée avec un appel à sleep(30)au début de globalSearchAction) dans le premier onglet

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


1
Vous venez de me lancer un défi, monsieur! :)
davidalger

Réponses:


21

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_closepour 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_startappel 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.


Le module uRapidFlow d'Unirgy ferme la session afin d'éviter ce problème, ce qui est agréable en quelque sorte, mais c'est frustrant dans la mesure où il est difficile de fournir des commentaires à l'utilisateur par la suite.
Peter O'Callaghan

@davidalger - Avec quel stockage de session déployez-vous généralement pour les sites clients?
Alan Storm

3
Re: verrouiller le fichier de session PHP, c'est moins pour l'intégrité des données que pour l'intégrité du fichier sur disque lui-même. Le fait d'avoir plusieurs processus s'ouvrant et écrivant sur des bits sur le disque (ce qu'est un fichier) entraînera rapidement une corruption des données. MySQL, redis et la plupart des bases de données sont conçus spécifiquement pour rester cohérents, même s'il y a plusieurs écritures presque en même temps. c'est-à-dire que ce n'est pas que le verrouillage a été ignoré, c'est qu'il n'est pas aussi indispensable.
Alan Storm

@AlanStorm - Une instance Memcached dédiée pour une installation à charge équilibrée, un système de fichiers pour les clusters de nœuds d'application unique. Le système de fichiers fonctionne mieux lorsque vous n'avez pas plusieurs nœuds car vous n'avez pas de latence IP.
davidalger

Correct, le verrouillage du fichier consiste à empêcher la corruption des données. Cependant, le maintien du verrou jusqu'à la fermeture de la session consiste à éviter la perte de données. Si deux processus chargent les données de session, les modifient puis les écrivent, l'un d'eux va voir ses modifications écrasées. Ne va généralement pas poser de problème critique, mais peut entraîner une perte de données et / ou des problèmes difficiles à déboguer.
davidalger
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.