この問題は、PHPセッションハンドラーによってロックがかけられていることが原因です。ですから、Magentoが何かを明示的にロックして管理リクエストをブロックしようとするのではなく、ファイルベースのセッションストレージの副作用そのものです。
セッションデータファイルが最初の(長時間実行される)要求によって開かれたときにセッションデータファイルに書き込みロックが設定されているため、呼び出し時にロックが解除されるまで2番目の要求がブロックされますsession_start
。Mage_Core_Model_Session_Abstract_Varien::start
これは100%再現可能です。私はあなたがしたのと同じ方法を使用してsleep(30)
、Mage_Adminhtml_IndexController::globalSearchAction
データベースセッションストレージを使用している場合、これは再現できないことに注意してください。根本原因を見つけた後、サンドボックスをdbセッションストレージに設定しましたが、問題を再現できなくなりました。そのため、Magentoのdbセッションハンドラーは、行レベルのロックを使用してセッション書き込みをロックしていないようです。アプリケーションは明らかに同じセッションに書き込む複数のスレッドを考慮していないため、セッションデータが失われる可能性があるため、これは興味深いと思います。読者への注意:本番環境でdbセッションストレージを使用してこれを解決しようとすることは決してありません。MySqlデータベースのオーバーロードにのみ適しています。
Redisなどのメモリベースのセッションストレージシステムを使用して動作を再現しようとしませんでしたが、セッションストア内のレコードのロックはおそらくこれらでも見落とされていると思われます。
これを回避するためsession_write_close
に、長時間実行されるジョブを開始する前にロックを解除するなどの方法を使用できます。ただし、セッションを閉じたばかりなので、これによりセッションへの書き込みができなくなります。そのため、Magentoでは全面的に容易に実装される可能性は低くなりますが、特定のルート/コントローラーに実装される可能性があります。
これを根本原因として特定するための私のテクニックは、Xdebugプロファイラーを有効にし、「cachegrind」ファイルを調べることでした。2番目の要求が完了したら、出力ファイル(約25 MBのログ)をMacCallGrindにロードし、呼び出し時間が28秒以上の呼び出しのパスに沿ってトレースをドリルダウンしました。これにより、最終的session_start
に実行までに約28秒かかった呼び出しに至り、調査の大きなポイントになりました。
編集:興味のある方のために、私はTwitterでMacCallGrindで見た「cachegrind」ファイルのスクリーンショットを投稿しました。