Dlaczego wolny admin-ajax.php wygląda jak atak
admin-ajax.php to jedyny endpoint AJAX całego WordPressa. Heartbeat, widgety kokpitu, page buildery, fragmenty koszyka, wyszukiwarka na żywo - każda interaktywna funkcja postuje do tego jednego pliku zamiast ładować stronę.
Kosztowny jest sam boot. Każde wywołanie robi pełny load WordPressa - plugins_loaded, init, admin_init - w kontekście wp-admin, a potem odpala action hook. Plugin, który pali 400 ms na admin_init, płaci tę cenę przy każdym przychodzącym wywołaniu, obojętnie która action je wywołała.
CPU rośnie, a log dostępu zapełnia się POST /wp-admin/admin-ajax.php - każdy request odpowiada dopiero po sekundach. Frontend może dalej chodzić dobrze, bo kryje go page cache, podczas gdy każda otwarta karta edytora dokłada kolejny strumień wywołań na ten sam endpoint.
Czyli dwie różne skargi lądują na tym samym pliku: każde wywołanie jest wolne i wywołania nie ustają. Obie zaczynają się od tego samego pytania - co tak naprawdę dzieje się w tych requestach?
Kto ciągle woła admin-ajax.php
Zanim zaczniesz winić botnet, policz wołających. Recydywiści są nudni:
| Wołający | Co robi |
|---|---|
| Heartbeat | Edytor wpisów postuje na admin-ajax.php mniej więcej co 15 sekund, póki jest otwarty. Trzy karty na tym samym wpisie to trzy strumienie wywołań. |
| Pluginy z pollingiem | Dashboardy backupów, skanery bezpieczeństwa, widgety czatu i panele analityki uderzają w endpoint w cyklu, niezależnie czy ktoś patrzy. |
| Ajax z frontendu | Fragmenty koszyka, filtry i handlery formularzy z hookiem nopriv działają też dla wylogowanych odwiedzających, więc prawdziwy ruch dokłada swoje obciążenie. |
| Twój własny handler | Każdy plugin albo motyw, który rejestruje akcję wp_ajax_, dzieli ten sam endpoint i ten sam koszt boota. |
Zakładka Network w przeglądarce pokazuje parametr action na wolnych wywołaniach, a log dostępu pokazuje częstotliwość. To mówi ci, który to strumień. Nie mówi, dlaczego wywołania kosztują sekundy.
Sprofiluj request, zobacz callback
Znajomość action nie nazywa jeszcze przyczyny. Dookoła siedzi cały stack pluginów - każdy callback podpięty pod plugins_loaded, init, admin_init i pod samą action leci na tym wywołaniu.
Znajdź wolne callbacki (Pro) profiluje jeden URL na twojej stronie. Wklej samo admin-ajax.php - albo stronę admina, która odpala wolne wywołania - a on odpala ukryty request z twoimi cookies admina, mierzy każdy callback powyżej progu i sortuje je po milisekundach z hookiem i plikiem źródłowym.
Skoro cały stack pluginów bootuje przy każdym wywołaniu, tabela wyników odpowiada na dwa pytania naraz: który callback spowalnia każde wywołanie ajax, a który leciał tylko w twojej action. Plugin palący 400 ms na admin_init siedzi na górze - hamuje każde wywołanie tak samo jak każdą stronę admina.
Sesje się zapisują. Sprofiluj, usuń albo napraw winowajcę, sprofiluj znowu - przed i po siedzą w tej samej tabeli historii.
Sprofilować można każdy URL tej samej strony, nie tylko endpoint ajax - ten sam request odpowiada na skargę na wolne wp-admin, kiedy całe ekrany admina wleką się.
Kiedy wolnym kawałkiem jest jedno zapytanie
Czasem callback to cienka skorupka, a sekundy siedzą w jednym zapytaniu - wyszukanie meta bez indeksu, table scan przy każdym pollu, wyszukiwanie z LIKE po wielkiej tabeli.
Slow Query Analyzer loguje każde zapytanie powyżej progu - domyślnie 0.05 s - wraz z wołającym, potem odpala EXPLAIN na każdym przechwycie i proponuje indeks gotowy do wykonania. admin-ajax.php liczy się jako request admina, więc domyślny tryb tylko dla admina łapie wywołania ajax bez zmieniania żadnego ustawienia.
Te dwa czytają ten sam request z dwóch końców. Profiler mówi „ten callback zajął 4 s”; analizator mówi „a 3.8 s z tego to ten SELECT na wp_postmeta”. Razem wskazują jeden plik i jedną linijkę SQL.
Znasz callback i zapytanie? To większość diagnozy - fix to patch, zamiennik albo bug report z liczbami w załączeniu.
Pro od $79/rok →Czego moduły nie zrobią - warto wiedzieć wcześniej
- Profiler wysyła GET. Nie potrafi powtórzyć dokładnego POST-a, którego wysłała twoja przeglądarka, więc handler czytający tylko pola $_POST widzi pusty request i wychodzi wcześnie. W takich przypadkach profiluj stronę admina, która odpala wywołanie - callbacki boota, które każde wywołanie ajax dzieli, i tak się mierzą.
- Handler zabezpieczony noncem umiera pierwszy. Jego własna robota zostaje niezmierzona na profilowanym requeście; wszystko dookoła - plugins_loaded, init, admin_init - i tak się mierzy.
- Wymagany jest HTTP loopback. Moduł profiluje, odpytując twoją własną stronę - firewall albo hosting blokujący requesty loopback blokuje też profilera.
- Find Slow Callbacks jest domyślnie wyłączony. Wdraża profilera jako MU-plugin, więc włączasz go, kiedy go potrzebujesz - do tego czasu nic nie leci.
- Nic z tego nie dławi Heartbeata ani nie limituje ajaxa. Moduły nazywają callback i zapytanie; usunięcie, podmiana albo zgłoszenie winowajcy zostaje twoją decyzją.
FAQ admin-ajax.php
Dlaczego admin-ajax.php jest tak wolny w WordPressie?
Każde wywołanie to pełny bootstrap WordPressa plus handler. Plugin robiący ciężką robotę na init albo admin_init spowalnia każde wywołanie, a jedno wolne zapytanie w handlerze robi to samo dla tej action. Duży wolumen wywołań z Heartbeata i pluginów z pollingiem mnoży koszt każdego wywołania.
Czy ruch na admin-ajax.php to atak?
Zwykle twój własny admin. Heartbeat edytora wpisów postuje mniej więcej co 15 sekund na otwartą kartę, a widgety kokpitu pollują w cyklu - w logu dostępu czyta się to dokładnie jak młócenie. Sprawdź parametr action na wywołaniach; prawdziwe zalewy istnieją, ale ogień bratobójczy to norma.
Mogę po prostu wyłączyć admin-ajax.php?
Nie. wp-admin od niego zależy - autosave'y, aktualizacje, większość interaktywnych ekranów - i sporo frontendów też. Zablokowanie endpointu zamienia wolną stronę na zepsutą. Do naprawy jest wolny callback albo gadatliwy wołający.
Czy Heartbeat API spowalnia WordPressa?
Heartbeat to najczęstszy recydywista we wp-admin, a każdy beat to pełny load WordPressa - na ciężkiej stronie każdy beat płaci pełny koszt boota. Nic w WP Multitool go nie dławi - profiler pokazuje ci, ile każdy beat naprawdę kosztuje.
Jak znaleźć, który plugin spowalnia admin-ajax.php?
Dwa podejścia. Find Slow Callbacks mierzy każdy callback w profilowanym requeście i sortuje je z hookiem i plikiem źródłowym, więc nazywa plugin spowalniający każde wywołanie. Slow Query Analyzer loguje zapytania, które wywołanie odpala, i oznacza te powyżej progu z podpowiedziami EXPLAIN.
Czy profiler powtarza wywołanie ajax z mojej przeglądarki?
Nie - odpala GET na podany przez ciebie URL, niosąc twoje cookies admina. Handler wymagający pól POST albo ważnego nonca wychodzi wcześnie, więc jego robota zostaje niezmierzona, a boot dookoła i tak się mierzy. W takich przypadkach profiluj stronę admina, która odpala wywołanie.
Czy plugin cache naprawi wolny admin-ajax.php?
Nie. Odpowiedzi ajax są dynamiczne i celowo niecache'owane, więc page cache nigdy ich nie dotyka. Każde wywołanie płaci pełne PHP plus handler - dlatego jedyną prawdziwą dźwignią jest obniżenie kosztu samego wywołania.
Nazwij callback stojący za każdym wywołaniem AJAX
Find Slow Callbacks i Slow Query Analyzer to moduły Pro - $79/rok za jedną stronę, a każdy płatny plan zawiera wszystkie 19 modułów. Włącz profilera, kiedy log dostępu zacznie się zapełniać.
Weź Pro - od $79/rok Poradnik: wolny admin Wszystkie plany na stronie cennika →