Долгосрочные запросы администратора страницы Блокировка других запросов

17

Если я вошел в бэкэнд Magento и выполнил какое-то задание, которое занимает много времени (глобальный поиск в больших каталогах, длительный поток данных и т. Д.), Мой веб-браузер откажется загружать другие страницы администратора только в этом браузере . Почему это происходит, и есть ли известная наука об обходных путях?

Если я

  1. Войти на страницу панели инструментов Magento

  2. Откройте вторую вкладку с любой страницей администратора Magento

  3. Выполните длительный глобальный поиск (смоделированный вызовом sleep(30)в начале globalSearchAction) на первой вкладке

  4. Попытка перезагрузить вторую вкладку

Ожидаемое поведение: вторая вкладка загружается с содержимым страницы немедленно

Фактическое поведение: вторая вкладка загружается только после завершения длительного глобального поиска

Кто-нибудь знает конкретно, почему это происходит? (Я предполагаю, что запросы консоли администратора Magento блокируют некоторый ресурс, необходимый Magento для начальной загрузки, но я не знаю, что это такое)

Кто-нибудь знает об исправлении / обходном пути?

Алан Сторм
источник
1
Вы, сэр, только что отправили меня на вызов! :)
Давидгер

Ответы:

21

Проблема вызвана блокировкой, установленной обработчиком сеанса 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.

davidalger
источник
Модуль Unirgy uRapidFlow закрывает сеанс, чтобы избежать этой проблемы, что приятно, но неприятно настолько, что затрудняет обратную связь с пользователем впоследствии.
Питер О'Каллаган
@davidalger - Какое хранилище сеансов вы обычно используете для клиентских сайтов?
Алан Шторм
3
Re: блокировка файла сеанса PHP, это меньше для целостности данных, чем для целостности самого файла на диске. Наличие нескольких процессов, открывающих и записывающих в биты на диске (что и есть файл), быстро приведет к повреждению данных. MySQL, Redis и большинство баз данных разработаны специально для обеспечения согласованности, даже если происходит многократная запись практически одновременно. то есть дело не в том, что блокировка была пропущена, а в том, что она не так необходима.
Алан Шторм
@AlanStorm - выделенный экземпляр Memcached для установки с балансировкой нагрузки, файловая система для кластеров узлов одного приложения. Файловая система работает лучше всего, когда у вас нет нескольких узлов, поскольку у вас нет задержки IP.
Давидгер
Правильно, блокировка файла - все о предотвращении повреждения данных. Однако удержание блокировки до закрытия сеанса означает предотвращение потери данных. Если два процесса загружают данные сеанса, изменяют их и затем записывают, один из них перезаписывает их модификации. Как правило, не представляет серьезную проблему, но может привести к потере данных и / или неприятным проблемам при отладке.
Давидгер