Тривалі запити сторінки адміністратора, що блокують інші запити


17

Якщо я ввійду в сервер Magento і виконую певне завдання, яке потребує тривалого часу (глобальний пошук у великих каталогах, тривалий потік даних тощо), мій веб-браузер відмовиться завантажувати інші сторінки адміністратора лише в цьому браузері . Чому це відбувається, і чи існує відома наука для обходу?

Тобто, якщо я

  1. Увійдіть на сторінку приладної панелі Magento

  2. Відкрийте другу вкладку на будь-якій сторінці адміністратора Magento

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

  4. Спроба перезавантажити другу вкладку

Очікувана поведінка: друга вкладка негайно завантажується вмістом сторінки

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

Хтось конкретно знає, чому це відбувається? (Я здогадуюсь, що консолі адміністратора Magento запитують блокування деякого ресурсу, який Magento потребує завантажувати, але я не знаю, що це таке)

Хтось знає про виправлення / вирішення?


1
Ви, пане, щойно відправили мене на виклик! :)
davidalger

Відповіді:


21

Проблема викликана блокуванням, розміщеним обробником сесії PHP. Отже, це не Magento явно щось блокує і намагається блокувати запити адміністратора, а майже побічний ефект від файлового сховища сеансу на основі файлів.

Блокування записи поміщаються в файл даних сесії , коли він відкритий початковим (довгограючий) запит, в результаті чого другого запиту до блоку , поки блокування не буде знято , коли вона викликає session_startвMage_Core_Model_Session_Abstract_Varien::start

Це на 100% відтворюється. Я використовував той самий метод, що і ви, додавши sleep(30)до вершиниMage_Adminhtml_IndexController::globalSearchAction

Варто зазначити, що це неможливо відтворити, якщо ви використовуєте сховище db сеансу. Після того як я знайшов першопричину, я встановив пісочницю для зберігання сеансів db і більше не міг відтворити проблему. Тож обробники сеансів db Magento, здавалося б, не використовують блокування рівня рядків для блокування записів сеансу. Мені це здається цікавим, оскільки він має потенціал до втрати даних сеансу, оскільки програма, очевидно, не враховує записування декількох потоків на один і той же сеанс. Примітка для читачів: Я б ніколи не використовував зберігання сеансів db у виробництві, щоб спробувати вирішити це, це добре лише для перевантаження вашої бази даних MySql.

Я не намагався відтворити поведінку за допомогою систем зберігання сеансів на основі пам’яті, таких як Redis, але я здогадуюсь, що блокування записів у сховищі сесій було, мабуть, і у них пропущено.

Існують методи, які можна уникнути подібного використання, session_write_closeщоб звільнити замок, перш ніж приступати до тривалої роботи. Але це також заважатиме писати на сеанс, оскільки ви тільки що закрили її. Таким чином, це, швидше за все, не буде легко впроваджено в Magento, але потенційно може бути реалізовано на конкретних маршрутах / контролерах.

Моя техніка виправити це як першопричину полягала в тому, щоб увімкнути профайлер Xdebug і перевірити файл "cachegrind". Після завершення другого запиту я завантажив вихідний файл (~ 25 МБ журналу) у MacCallGrind і просверлився в слід, слідуючи за маршрутом викликів, де час включення становив 28 секунд або більше. Це в кінцевому підсумку призвело мене до session_startдзвінка, який зайняв ~ 28 секунд для запуску, що дало мені чудову точку для досліджень.

EDIT: Для зацікавлених людей я опублікував скріншот файлу "cachegrind", переглянутого в MacCallGrind у Twitter.


Модуль uRapidFlow Unirgy закриває сеанс, щоб уникнути цього питання, що є приємним певним чином, але це засмучує стільки, скільки ускладнює подання відгуку користувачеві згодом.
Пітер О'Каллаган

@davidalger - Яке сховище сеансу ви зазвичай розгортаєте для клієнтських сайтів?
Алан Шторм

3
Re: блокування файлу сеансу PHP, це менше для цілісності даних, ніж для цілісності самого файлу на диску. Відкриття та запис декількох процесів у біти на диску (що таке файл) швидко призведе до пошкодження даних. MySQL, redis та більшість баз даних розроблені спеціально для того, щоб залишатися послідовними, навіть якщо є кілька записів майже в один і той же час. тобто це не те, що блокування було пропущено, це не так критично потрібно.
Алан Шторм

@AlanStorm - виділений екземпляр Memcached для збалансованої навантаження установки, файлова система для кластерів одного вузла додатків. Файлова система найкраще працює там, де у вас немає декількох вузлів, оскільки у вас немає затримки IP-адреси.
davidalger

Правильне, блокування файлу - це все щодо запобігання пошкодження даних. Однак утримання блокування до закриття сеансу - це запобігання втраті даних. Якщо два процеси завантажують дані сеансу, змінюють їх і потім виписують, в одному з них буде перезаписано його модифікації. Як правило, це не стане критичною проблемою, але може призвести до втрати даних та / або до важких проблем з налагодженням.
davidalger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.