Problem jest spowodowany blokadą umieszczoną przez moduł obsługi sesji PHP. Więc to nie Magento jawnie coś blokuje i próbuje blokować żądania administratora, ale prawie efekt uboczny per se przechowywania pamięci sesji.
Blokada zapisu jest umieszczony w pliku danych sesji, gdy jest on otwarty przez początkowe (długo pracuje) żądanie, powodując drugą prośbę do bloku, aż blokada zostanie zwolniona, gdy nazywa session_start
sięMage_Core_Model_Session_Abstract_Varien::start
Jest to w 100% powtarzalne. Użyłem tej samej metody, co ty, dodając sleep(30)
do góryMage_Adminhtml_IndexController::globalSearchAction
Warto zauważyć, że nie można tego odtworzyć, jeśli używasz pamięci sesji db. Po znalezieniu głównej przyczyny ustawiłem piaskownicę na przechowywanie sesji db i nie mogłem już odtworzyć problemu. Więc programy obsługi sesji db Magento najwyraźniej nie używają blokowania na poziomie wiersza do blokowania zapisów sesji. Uważam to za interesujące, ponieważ może powodować utratę danych sesji, ponieważ aplikacja oczywiście nie rozlicza wielu wątków zapisujących do tej samej sesji. Uwaga dla czytelników: nigdy nie używałbym pamięci sesji sesji db w produkcji, aby spróbować rozwiązać ten problem, jest to dobre tylko do przeciążania bazy danych MySql.
Nie próbowałem odtworzyć tego zachowania przy użyciu systemów pamięci sesji opartych na pamięci, takich jak Redis, ale zgaduję, że blokowanie rekordów w sklepie sesji prawdopodobnie zostało w nich przeoczone.
Istnieją techniki, które można zastosować, aby tego uniknąć, np. session_write_close
Zwolnienie blokady przed rozpoczęciem długotrwałej pracy. Ale to również uniemożliwi Ci pisanie na sesję, ponieważ właśnie ją zamknąłeś. Tak więc prawdopodobnie nie będzie łatwo zaimplementować go w Magento, ale potencjalnie może zostać zaimplementowany na określonych trasach / kontrolerach.
Moją techniką przypisywania tego jako głównej przyczyny było włączenie profilera Xdebug i sprawdzenie pliku „cachegrind”. Po zakończeniu drugiego żądania załadowałem plik wyjściowy (~ 25 MB dziennika) do MacCallGrind i zagłębiłem się w ślad zgodnie ze ścieżką wywołań, gdzie czas włączenia wynosił 28 sekund lub więcej. To ostatecznie doprowadziło mnie do session_start
rozmowy, która zajęła ~ 28 sekund, co dało mi świetny punkt do zbadania.
EDYCJA: Dla zainteresowanych zamieściłem zrzut ekranu pliku „cachegrind” oglądanego w MacCallGrind na Twitterze.