如果我登录了Magento的后端并执行需要很长时间的任务(全球搜索大型目录,长期运行的数据流等),我的Web浏览器将拒绝加载其他管理页面 仅在该浏览器中. 。为什么会发生这种情况,并且有任何可解决方法的科学?

也就是说,如果我

  1. 登录到Magento的仪表板页面

  2. 使用任何Magento管理页面打开第二个选项卡

  3. 执行长期运行的全局搜索(模拟调用 sleep(30) 在开始时 globalSearchAction)在第一个选项卡中

  4. 尝试重新加载第二个选项卡

预期行为:第二个标签加载带有页面内容

实际行为:第二个选项卡仅加载长期运行的全局搜索完成

有谁知道为什么会发生这种情况? (我的猜测是Magento Admin Console请求锁定一些资源Magento需要进行引导,但我不知道那是什么)

有人知道修复/解决方法吗?

有帮助吗?

解决方案

问题是由PHP会话处理程序放置的锁引起的。因此,它不是明确锁定某些内容并试图阻止管理员请求的,而是基于文件的会话存储的副作用。

在会话数据文件由初始(长期运行)请求打开时,将在会话数据文件上放置一个写锁,导致第二个请求阻止,直到锁定锁定时释放锁 session_startMage_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 Profiler并检查“ Cachegrind”文件。第二个请求完成后,我将输出文件(〜25 MB日志)加载到 MacCallGrind 并按照呼叫路径的路径钻入轨迹,其中包含时间为28秒或更长。这最终使我进入了 session_start 呼叫花费了约28秒的运行,为我提供了一个很好的研究。

编辑: 对于有兴趣的人,我 发布了屏幕截图 在Twitter上查看的MacCallGrind中查看的“ cachegrind”文件。

许可以下: CC-BY-SA归因
scroll top