Przejdź do treści
Zapolu

4 czerwca 2026, Luboš Zápotočný

Dlaczego checkout pada przy 10% obciążenia serwera

Serwery mają rezerwy, checkout nie odpowiada. Blokady w bazie, cache stampede i synchroniczne wywołania płatności: awarie, których autoscaling nie rozwiąże.

To jeden z najbardziej dezorientujących incydentów, z jakimi mierzy się zespół e-commerce. Startuje kampania, w checkoucie pojawiają się timeouty, a dashboardy pokazują prawidłowe wartości: CPU na 10%, pamięć w normie, duży zapas mocy. Pierwszą reakcją jest zwykle dodanie serwerów. Nowe instancje uruchamiają się, pozostają bezczynne obok dotychczasowych, a checkout nadal nie odpowiada.

Dezorientacja bierze się z błędnego wyobrażenia o tym, jak to działa. Obciążenie ma dwa składniki: pracę i czekanie. Twoje serwery stoją w kolejkach, a kolejek nie widać na wykresie CPU.

Najczęstsze przyczyny

Rywalizacja o blokady w bazie. Checkout to moment, w którym sklep przestaje czytać i zaczyna pisać: rezerwacja stanu, utworzenie zamówienia, zapis adresu. Te zapisy serializują się na blokadach wierszy, a ruch z kampanii skupia je na tych samych kilku najczęściej zapisywanych wierszach: licznikach sekwencji zamówień, tabelach zamówień i koszyków oraz rezerwowanym stanie magazynowym. Każda transakcja trzyma swoje blokady, czekając na zakończenie innych operacji. Przepustowość gwałtownie spada, a użycie CPU pozostaje niskie. Na Magento widać to w logach jako błędy lock-wait timeout i zakleszczenia z MySQL.

Cache stampede. Często odpytywany wpis w cache’u (strona kategorii, w którą celuje każda reklama) wygasa w szczycie ruchu. Każde żądanie, które nie trafia w cache, regeneruje stronę równocześnie z pozostałymi, obciążając bazę identycznymi, kosztownymi zapytaniami. Baza dostaje jedną kopię tej pracy na każde równoczesne żądanie.

Synchroniczne wywołania zewnętrznych API na ścieżce checkoutu. Koszty dostawy, autoryzacja płatności, wyliczenie podatku, kontrola antyfraudowa: każde z nich to wywołanie sieciowe do zewnętrznego systemu, wykonywane, podczas gdy Twój worker trzyma połączenie, a często i transakcję bazodanową. Kiedy jeden dostawca zwalnia z 200 ms do 10 sekund przy tym samym ruchu z kampanii, kolejne workery jeden po drugim blokują się na tym wywołaniu. Checkout pozostaje wtedy niedostępny tak długo, jak długo ten dostawca jest wolny.

Wyczerpanie workerów i połączeń. Trzy powyższe problemy mają wspólny czynnik, który je nasila: workery, które czekają, wciąż zajmują swój slot i swoje połączenie z bazą. Procesy PHP-FPM zwymiarowane na zwykły ruch w dni robocze zapełniają się zablokowanymi żądaniami, nowe żądania w ogóle nie dostają ani workera, ani połączenia i niedostępne jest już wszystko, co wciąż potrzebuje workera PHP, nawet jeśli dana strona prawie nic nie robi.

Żaden z tych czterech problemów nie jest problemem sprzętowym, dlatego autoscaling ich nie rozwiązuje. Nowe instancje dołączają do tej samej kolejki po tę samą blokadę wiersza za tym samym wolnym dostawcą. Dodatkowa moc czeka równolegle, zamiast zwiększać przepustowość.

Jak to zobaczyć zawczasu

W diagnozie trzeba przestać patrzeć na wykorzystanie zasobów, a zacząć na czas: na co schodzą milisekundy żądania checkoutu, na pracę czy na czekanie na blokady, cache i zewnętrzne API? Rozproszone trace’y odpowiadają na to wprost; log wolnych zapytań i liczniki oczekiwania na blokady w bazie odpowiadają tanio. Jeśli przed następną kampanią masz dodać tylko jeden wykres, niech to będą czasy oczekiwania na blokady.

Poprawki wynikają z diagnozy i w większości są rutynowe: timeouty na każdym wywołaniu do zewnętrznego API i cache’owane fallbacki wszędzie tam, gdzie nieaktualna odpowiedź nie szkodzi (nieco nieaktualny koszt dostawy nic nie psuje, ale autoryzacja płatności musi odbywać się w czasie rzeczywistym), ochrona przed stampede, żeby jeden proces odbudowywał często odpytywany klucz, a reszta zwracała starszą wersję, wyniesienie mniej ważnych zapisów z transakcji do kolejki i rezerwowanie stanu magazynowego tak późno na ścieżce zakupowej, jak pozwala na to biznes, zamiast blokowania go już od koszyka. Które z nich mają znaczenie dla Twojego sklepu, to kwestia empiryczna. Audyt wydajności odpowiada na to na podstawie Twoich własnych trace’ów, a nasz DevOps dba o to, by poprawki nadal działały.

Większość takich incydentów okazuje się problemem współbieżności, więc zanim kupisz kolejne serwery, zacznij od trace’a.