Je m'occupe d'une boutique Magento avec 400-500 visiteurs et 40-50 commandes par jour. Récemment, le système a été mis à niveau de Magento EE 1.14.2.4 vers Magento EE 1.14.3.2 et j'ai remarqué quelques exceptions étranges dans les journaux:
exception 'Mage_Core_Model_Session_Exception' in
/var/www/.../app/code/core/Mage/Core/Model/Session/Abstract/Varien.php:418
Je cherchais cette exception et je sais qu'elle est déclenchée car le code de validation de session suivant ne parvient pas à valider la session:
class Mage_Core_Model_Session_Abstract_Varien extends Varien_Object
{
// ...
protected function _validate()
{
// ...
if ($this->useValidateSessionExpire()
&& isset($sessionData[self::VALIDATOR_SESSION_EXPIRE_TIMESTAMP])
&& $sessionData[self::VALIDATOR_SESSION_EXPIRE_TIMESTAMP] < time() ) {
Ce bloc if a été ajouté au fichier avec la dernière version de Magento. Et c'est apparemment un changement de freinage, voir plus de détails ci-dessous.
L'exception se produit assez souvent, comme une douzaine de fois par jour. mais je ne suis pas en mesure de recréer des conditions qui conduisent à l'exception, sauf si je mets littéralement vrai dans la condition ci-dessus. Les exceptions se produisent le plus souvent sur les pages de détails du produit et à la dernière étape de la vérification d'une page. La boutique est une boutique b2b, l'utilisateur doit être connecté pour voir la page du produit ou pour pouvoir commander, signifie que l'utilisateur est redirigé vers les pages de connexion lorsque la session est invalidée / expirée. Pour le moment, il est plus important pour moi de résoudre ce problème lors du paiement.
Que se passe-t-il du point de vue de l'utilisateur: l'utilisateur remplit le panier, passe à la caisse et atteint la dernière étape, puis il / elle clique sur le bouton "soumettre la commande" et rien ne se passe. Dans les coulisses, JS de Magento effectue une requête AJAX et JS s'attend à recevoir JSON en retour, mais si cette erreur se produit, le code HTML de la page de connexion est renvoyé, ce qui ne peut pas être analysé par JavaScript et ne fait rien. C'est super déroutant pour les utilisateurs.
Eh bien, ce n'est pas un scénario utilisateur complet, nous avons contacté les utilisateurs et ils nous ont dit qu'ils ont attendu quelques jours entre le remplissage du panier et la soumission de la commande, ce que cela signifie exactement est difficile à comprendre, car les gens ne s'en souviennent tout simplement pas.
Durée de vie de la session PHP - 350000 (~ 4 jours en secondes) Durée de vie du cookie - 345600 (4 jours)
Voici la vraie question: comment puis-je savoir quel type de comportement utilisateur conduit à l'exception?
MISE À JOUR Jusqu'à présent, je sais que l'exception se produit dans les classes suivantes en fonction de la demande faite, pour moi cela ne signifie malheureusement rien.
/catalogsearch/result/?q=… Mage_Core_Model_Session
/checkout/cart/ Mage_Core_Model_Session
/checkout/onepage/saveOrder/… Mage_Rss_Model_Session
/customer/account/loginPost/ Mage_Core_Model_Session
/customer/account/loginPost/ Mage_Reports_Model_Session
/customer/account/logout/ Mage_Reports_Model_Session
/catalog/product/view/… Mage_Reports_Model_Session
/catalog/product/view/… Mage_Tag_Model_Session
MISE À JOUR 2 : les sessions sont stockées dans des fichiers et nettoyées par le garbage collector de la session PHP, que ce soit un bon choix ou non est hors de portée de cette question.
la source
Réponses:
Après un débogage avancé, un suivi de session et une réflexion sur toute cette magie, j'ai pu reproduire le problème et en comprendre la raison. J'ai préparé une petite illustration de timing, vous pouvez la voir ci-dessous.
/sales/order/save/...
demande)Voici comment reproduire:
Raison:
Il y a certaines sessions qui ne sont instanciées que sur des demandes données, par exemple, qui
Mage_Rss_Model_Session
ne sont instanciées que lors du paiement réel et non lors de la navigation dans le catalogue. En même temps, l'horodatage d'expiration de la session n'est défini que lorsque la session a été instanciée. Cela signifie que s'il y a eu suffisamment de temps entre deux extractions et que la session n'a pas été interrompue entre-temps (parce que l'utilisateur s'est déconnecté ou que le cookie a expiré), le nouveau code Magento considérera cette session comme ne passant pas la validation et lèvera une exception, ce qui semble quelque peu étrange à moi.Comment réparer:
Eh bien, j'ai peu d'options:
Comment ai-je compris:
J'ai commencé par ajouter ce qui suit au code d'origine de
Mage_Core_Model_Session_Abstract_Varien
cela m'a donné un bon aperçu des classes affectées et de leur corrélation et de la durée de la session. Mais cela n'expliquait pas pourquoi cela se produisait et quelles actions des utilisateurs entraînaient le problème.
Ensuite, j'ai commencé à réfléchir à la façon de suivre toutes les modifications apportées aux données de session et j'ai rencontré cette question /superuser/368231/automatic-versioning-upon-file-change-modify-create-delete que j'ai décidé de donner. un essai
git
et uneincron
combinaison, mais après l'avoir implémenté et testé dans un bac à sable, j'ai réalisé que je manquerai d'espace disque très rapidement en production.J'ai décidé de construire un petit script PHP qui décodera les données de session et rédigera des journaux pour chaque session. Ce script a été appelé par
incron
et voici l'
incrontab
entrée correspondanteexemple de sortie
PS:
Versions actuelles des deux
ne sont pas en mesure de gérer l'exception ci-dessus lors de la demande AJAX. Ils n'affichent littéralement rien à l'utilisateur, tandis que l'utilisateur est effectivement déconnecté!
PPS:
apparemment, les versions de Magento CE 1.9.3.x sont également affectées, voir https://github.com/OpenMage/magento-mirror/blame/magento-1.9/app/code/core/Mage/Core/Model/Session/Abstract/ Varien.php
PPPS:
Quand j'ai dit "Supprimez ce code en attendant." Je voulais dire exclure le bloc suivant
vous pouvez le faire de différentes manières, notamment:
$this->useValidateSessionExpire()
retour vraila source
<Mage_Rss>
et cela a résolu le problème (correction temporaire) et j'ai déposé le ticket avec le support de magento.Une autre façon de résoudre ce problème (et d'améliorer la validation de la session)
ColinM @ https://github.com/OpenMage/magento-lts
Source: https://github.com/OpenMage/magento-lts/commit/de06e671c09b375605a956e100911396822e276a
Mise à jour:
Correction de l'
web/session/use_http_x_forwarded_for option
option désactivée ... https://github.com/OpenMage/magento-lts/pull/457/commits/ec8128b4605e82406679c3cd81244ddf3878c379la source
Comment stockez-vous les sessions? (c'est-à-dire dans var / session / ou dans la base de données, ou en utilisant d'autres moteurs de mise en cache tels que Redis ou Memcached)
Quel que soit le système utilisé, assurez-vous que vos autorisations d'écriture sont correctes
var/session/
(généralement définies sur 755 pour les répertoires et 644 pour les fichiers), ou si vous utilisez Redis ou Memcache, assurez-vous que vos paramètres de connexion et de délai d'attente sont bons pour ceux .Inchoo a un bon tutoriel pour Redis: http://inchoo.net/magento/using-redis-cache-backend-and-session-storage-in-magento/
Si vous utilisez Memcache, consultez cet article (il fait référence à la v1.10, mais ne devrait pas être très différent): http://www.magestore.com/magento/magento-sessions-disappearing-with-memcache-turned-on.html
De plus, si vous utilisez quelque chose comme Varnish, il y a eu des problèmes dans le passé avec des sessions où il était nécessaire de perforer certaines pages.
Enfin, si vous utilisez le système de fichiers pour vos sessions, vous pourriez trouver un soulagement en basculant simplement le
<session_save>
nœud de votrelocal.xml
sur "db" au lieu de "fichiers".De cela
<session_save><![CDATA[files]]></session_save>
Pour ça
<session_save><![CDATA[db]]></session_save>
la source
Le détail d'Anton Boritskiy est fantastique. Mais au lieu d'exclure ce bloc, vous pouvez faire une copie locale afin de ne pas éditer le noyau et réécrire le bloc comme:
Cela garantit que la comparaison entre time () et session_expire_timestamp n'est exécutée que lorsque la clé existe et que lorsqu'une session est trouvée qui n'a pas la clé (c'est-à-dire une session antérieure à la version 1.9.3), la clé est ajoutée.
la source