El problema es causado por un bloqueo colocado por el controlador de sesión PHP. Por lo tanto, no se trata de que Magento bloquee explícitamente algo e intente bloquear las solicitudes de administración, sino casi un efecto secundario per-se del almacenamiento de sesión basado en archivos.
Un bloqueo de escritura se lo coloca en el archivo de datos de sesión cuando se abre por la solicitud inicial (de larga duración), haciendo que la segunda solicitud al bloque hasta que el bloqueo se libera cuando se llama session_start
enMage_Core_Model_Session_Abstract_Varien::start
Esto es 100% reproducible. Usé el mismo método que usaste, agregando un sleep(30)
a la parte superior deMage_Adminhtml_IndexController::globalSearchAction
Vale la pena señalar que esto no se puede reproducir si está utilizando el almacenamiento de sesión db. Después de encontrar la causa raíz, configuré un sandbox para el almacenamiento de sesión db y ya no pude reproducir el problema. Por lo tanto, los manejadores de sesión de db que Magento aparentemente no utiliza el bloqueo de nivel de fila para bloquear las escrituras de sesión. Esto me parece interesante, ya que tiene el potencial de pérdida de datos de la sesión, ya que la aplicación obviamente no tiene en cuenta múltiples hilos que escriben en la misma sesión. Nota para los lectores: nunca usaría el almacenamiento de sesión db en producción para tratar de resolver esto, solo es bueno para sobrecargar su base de datos MySql.
No intenté reproducir el comportamiento utilizando sistemas de almacenamiento de sesión basados en memoria como Redis, pero supongo que el bloqueo de los registros en el almacén de sesión probablemente también se pasó por alto en estos.
Hay técnicas que podrían emplearse para evitar esto, como usar session_write_close
para liberar el bloqueo antes de comenzar un trabajo de larga duración. Pero esto también le impediría escribir en la sesión ya que la acaba de cerrar. Por lo tanto, no es probable que se implemente fácilmente en todos los ámbitos en Magento, pero podría implementarse en rutas / controladores específicos.
Mi técnica para fijar esto como la causa raíz era habilitar el perfilador Xdebug y examinar el archivo "cachegrind". Una vez que se completó la segunda solicitud, cargué el archivo de salida (~ 25 MB de registro) en MacCallGrind y profundicé en el seguimiento siguiendo la ruta de las llamadas donde el tiempo de inclusión fue de 28 segundos o más. Esto finalmente me llevó a la session_start
llamada, que tardó unos 28 segundos en ejecutarse, lo que me dio un gran punto para investigar.
EDITAR: Para los interesados, publiqué una captura de pantalla del archivo "cachegrind" visto en MacCallGrind en Twitter.