Если я вошел в бэкэнд Magento и выполнил какое-то задание, которое занимает много времени (глобальный поиск в больших каталогах, длительный поток данных и т. Д.), Мой веб-браузер откажется загружать другие страницы администратора только в этом браузере . Почему это происходит, и есть ли известная наука об обходных путях?
Если я
Войти на страницу панели инструментов Magento
Откройте вторую вкладку с любой страницей администратора Magento
Выполните длительный глобальный поиск (смоделированный вызовом
sleep(30)
в началеglobalSearchAction
) на первой вкладкеПопытка перезагрузить вторую вкладку
Ожидаемое поведение: вторая вкладка загружается с содержимым страницы немедленно
Фактическое поведение: вторая вкладка загружается только после завершения длительного глобального поиска
Кто-нибудь знает конкретно, почему это происходит? (Я предполагаю, что запросы консоли администратора Magento блокируют некоторый ресурс, необходимый Magento для начальной загрузки, но я не знаю, что это такое)
Кто-нибудь знает об исправлении / обходном пути?
источник
Ответы:
Проблема вызвана блокировкой, установленной обработчиком сеанса PHP. Так что это не Magento, явно блокирующее что-то и пытающееся блокировать запросы администратора, а почти побочный эффект как такового хранения файловых сеансов.
Блокировка записи помещаются в файл данных сессии , когда он открыт начальным (долгоиграющий) запрос, в результате чего второго запроса к блоку , пока блокировка не будет снята , когда она вызывает
session_start
вMage_Core_Model_Session_Abstract_Varien::start
Это на 100% воспроизводимо. Я использовал тот же метод, что и вы, добавив
sleep(30)
в началоMage_Adminhtml_IndexController::globalSearchAction
Стоит отметить, что это не может быть воспроизведено, если вы используете хранилище сеансов БД. После того, как я нашел основную причину, я установил «песочницу» в хранилище сеансов db и больше не мог воспроизвести проблему. Таким образом, обработчики сеансов db, которые Magento имеет, по-видимому, не используют блокировку на уровне строк для блокировки записи сеансов. Я нахожу это интересным, поскольку он может привести к потере данных сеанса, поскольку приложение, очевидно, не учитывает запись нескольких потоков в один и тот же сеанс. Примечание для читателей: я бы никогда не использовал хранилище сеансов в базе данных, чтобы попытаться решить эту проблему, это хорошо только для перегрузки базы данных MySql.
Я не пытался воспроизвести поведение, используя системы хранения сессий на основе памяти, такие как Redis, но я предполагаю, что блокировка записей в хранилище сессий, вероятно, также игнорировалась.
Чтобы избежать этого, можно использовать методы, такие как
session_write_close
снятие блокировки перед началом длительной работы. Но это также помешает вам писать в сеанс, так как вы только что закрыли его. Таким образом, он вряд ли будет легко реализован в Magento, но потенциально может быть реализован на определенных маршрутах / контроллерах.Моя методика закрепления этого как основной причины состояла в том, чтобы включить профилировщик Xdebug и проверить файл «cachegrind». По завершении второго запроса я загрузил выходной файл (журнал ~ 25 МБ) в MacCallGrind и углубился в трассировку, следуя пути вызовов, где время включения составляло 28 секунд или больше. В конечном итоге это привело меня к
session_start
вызову, который занял ~ 28 секунд, что дало мне отличную возможность для исследования.РЕДАКТИРОВАТЬ: Для заинтересованных, я опубликовал скриншот файла «cachegrind», который просматривается в MacCallGrind в Twitter.
источник