Проблема викликана блокуванням, розміщеним обробником сесії 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.