Я слежу за магазином Magento с 400-500 посетителями и 40-50 заказами в день. Недавно система была обновлена с Magento EE 1.14.2.4 до Magento EE 1.14.3.2, и я заметил некоторые странные исключения в журналах:
exception 'Mage_Core_Model_Session_Exception' in
/var/www/.../app/code/core/Mage/Core/Model/Session/Abstract/Varien.php:418
Я преследовал это исключение, и я знаю, что оно запускается, потому что следующий код проверки сеанса не в состоянии проверить сеанс:
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() ) {
Этот if-блок был добавлен в файл с последним выпуском от Magento. И это, по-видимому, тормозное изменение, подробности см. Ниже.
Исключение происходит довольно часто, например, дюжина раз в день. но я не могу воссоздать условия, которые приводят к исключению, если я буквально не верю в условие выше. Исключения чаще всего встречаются на страницах с описанием товара и на последнем этапе оформления одной страницы. Магазин является магазином b2b, пользователь должен войти в систему, чтобы увидеть страницу продукта или иметь возможность оформить заказ. Это означает, что пользователь перенаправляется на страницы входа в систему, когда сеанс аннулирован / истек срок действия. На данный момент для меня важнее исправить эту проблему во время оформления заказа.
Что происходит с точки зрения пользователя: пользователь заполняет корзину, переходит к оформлению заказа и достигает последнего шага, затем нажимает кнопку «отправить заказ», и ничего не происходит. За кулисами JS Magento выполняет запрос AJAX, и JS ожидает получить JSON обратно, но в случае возникновения этой ошибки возвращается HTML-код страницы входа, который не может быть проанализирован JavaScript, и он просто ничего не делает. Это очень запутанно для пользователей.
Ну, это не полный пользовательский сценарий, мы связались с пользователями, и они сказали нам, что они ждали несколько дней между заполнением корзины и отправкой заказа, что это точно означает, что трудно понять, потому что люди просто не помнят этого.
Время жизни сессии PHP - 350000 (~ 4 дня в секундах) Время жизни куки - 345600 (4 дня)
Вот актуальный вопрос: как я могу узнать, какое поведение пользователя приводит к исключению?
ОБНОВЛЕНИЕ До сих пор я знаю, что исключение происходит в следующих классах согласно сделанному запросу, для меня это ничего не значит, к сожалению.
/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
ОБНОВЛЕНИЕ 2 : сессии хранятся в файлах и очищаются сборщиком мусора сессий PHP, независимо от того, является ли это хорошим выбором или нет, выходит за рамки этого вопроса.
источник
Ответы:
После некоторой продвинутой отладки, отслеживания сеанса и обдумывания всей этой магии я смог воспроизвести проблему и понять причину ее возникновения. Я подготовил небольшую временную иллюстрацию, вы можете увидеть ее ниже.
/sales/order/save/...
запрос)Вот как воспроизвести:
Причина:
Существуют определенные сеансы, которые создаются только по заданным запросам, например,
Mage_Rss_Model_Session
создаются только во время фактической проверки, а не при просмотре каталога. В то же время отметка времени истечения сеанса устанавливается только тогда, когда был создан экземпляр сеанса. Это означает, что если между двумя извлечениями было достаточно времени, а сеанс не был прерван (поскольку пользователь вышел из системы или истек срок действия файла cookie), новый код Magento будет считать этот сеанс не прошедшим проверку и выдаст исключение, что звучит несколько странно для мне.Как исправить:
Ну, у меня есть несколько вариантов:
Как я это выяснил:
Я начал с добавления следующего к исходному коду
Mage_Core_Model_Session_Abstract_Varien
это дало мне хорошее представление о затронутых классах и их взаимосвязи, а также о том, сколько сеансов истекло. Но это не объясняло, почему это происходит и какие действия пользователя приводят к проблеме.
Тогда я начал думать о том, как я могу отследить все изменения в данных сеанса, и наткнулся на этот вопрос /superuser/368231/automatic-versioning-upon-file-change-modify-create-delete, который я решил дать попытка
git
иincron
комбинация, но после того, как я реализовал это и протестировал в песочнице, я понял, что на производстве у меня будет очень мало свободного места.Я решил создать небольшой скрипт PHP, который будет декодировать данные сеанса и записывать журналы для каждой сессии. Этот скрипт был вызван
incron
и вот соответствующая
incrontab
записьобразец вывода
PS:
Актуальные версии обоих
не могут обработать указанное выше исключение во время запроса AJAX. Они буквально ничего не отображают для пользователя, в то время как пользователь фактически выходит из системы!
PPS:
версии Magento CE 1.9.3.x также подвержены уязвимости, см. https://github.com/OpenMage/magento-mirror/blame/magento-1.9/app/code/core/Mage/Core/Model/Session/Abstract/ Varien.php
PPPS:
Когда я сказал: «Тем временем удалите этот код». Я имел ввиду исключение следующего блока
Вы можете сделать это многими способами, в том числе:
$this->useValidateSessionExpire()
возвращающиеисточник
<Mage_Rss>
и это решило проблему (временное исправление) и подал заявку с поддержкой magento.Другой способ исправить это (и улучшить проверку сеанса)
ColinM @ https://github.com/OpenMage/magento-lts
Источник: https://github.com/OpenMage/magento-lts/commit/de06e671c09b375605a956e100911396822e276a
Обновить:
Исправить
web/session/use_http_x_forwarded_for option
отключенную опцию ... https://github.com/OpenMage/magento-lts/pull/457/commits/ec8128b4605e82406679c3cd81244ddf3878c379источник
Как вы храните сессии? (т.е. в var / session / или в БД, или используя другие механизмы кэширования, такие как Redis или Memcached)
Независимо от того, что вы используете, убедитесь, что у вас правильные разрешения на запись
var/session/
(обычно это 755 для dirs и 644 для файлов), или если вы используете Redis или Memcache, убедитесь, что ваши настройки подключения и тайм-аута подходят для тех, ,В Inchoo есть хороший учебник для Redis: http://inchoo.net/magento/using-redis-cache-backend-and-session-storage-in-magento/
При использовании Memcache ознакомьтесь с этой статьей (она ссылается на v1.10, но не должна сильно отличаться): http://www.magestore.com/magento/magento-sessions-disappearing-with-memcache-turned-on.html
Кроме того, если вы используете что-то вроде Varnish, в прошлом были проблемы с сеансами, когда требовалось пробивать определенные страницы.
Наконец, если вы используете файловую систему для своих сессий, вы можете найти облегчение, просто переключив
<session_save>
узел в вашемlocal.xml
«db» вместо «files».Из этого
<session_save><![CDATA[files]]></session_save>
К этому
<session_save><![CDATA[db]]></session_save>
источник
Деталь Антона Борицкого фантастическая. Но вместо исключения этого блока вы можете сделать локальную копию, чтобы не редактировать ядро и переписать блок следующим образом:
Это гарантирует, что сравнение между time () и session_expire_timestamp выполняется только тогда, когда ключ существует, и что при обнаружении сеанса, у которого нет ключа (то есть до сеанса до 1.9.3), ключ добавляется.
источник