Jeśli zaloguję się do backendu Magento i wykonam jakieś zadanie, które zajmuje dużo czasu (globalne wyszukiwanie w dużych katalogach, długo działający przepływ danych itp.), Moja przeglądarka internetowa odmówi załadowania innych stron administracyjnych tylko w tej przeglądarce . Dlaczego tak się dzieje i czy istnieje jakakolwiek znana metoda obejścia tego problemu?
To znaczy, jeśli ja
Zaloguj się na stronie pulpitu Magento
Otwórz drugą kartę z dowolną stroną administracyjną Magento
Wykonaj długo działające wyszukiwanie globalne (symulowane wywołaniem
sleep(30)
na początkuglobalSearchAction
) w pierwszej zakładceSpróbuj ponownie załadować drugą kartę
Oczekiwane zachowanie: Druga karta natychmiast ładuje zawartość strony
Rzeczywiste zachowanie: druga karta ładuje się dopiero po zakończeniu długotrwałego wyszukiwania globalnego
Czy ktoś wie, dlaczego tak się dzieje? (Domyślam się, że żądania konsoli administracyjnej Magento blokują jakiś zasób, którego Magento potrzebuje do uruchomienia, ale nie wiem co to jest)
Czy ktoś wie o poprawce / obejściu?
źródło
Odpowiedzi:
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.
źródło