Aplikacja w Pythonie zwalnia: co sprawdzić przed skalowaniem?
Gdy aplikacja w Pythonie zwalnia pod obciążeniem, zacznij od pomiaru konkretnej czynności użytkownika. Trzeba ustalić, czy czas zabiera pobieranie danych, obliczenia, oczekiwanie na inny system czy wyświetlanie wyniku. Dopiero wtedy można porównać koszt poprawy aplikacji z kosztem zwiększenia zasobów serwera.
Jeżeli opóźnienia już blokują przyjmowanie zamówień albo pracę zespołu, wykonawca powinien najpierw ustabilizować usługę. Tymczasowe zwiększenie zasobów może być częścią takiej interwencji. Warto od razu ustalić, jak zostanie sprawdzony jego efekt i kiedy zapadnie decyzja o dalszym rozwiązaniu, żeby doraźny wydatek nie stał się stałym kosztem bez uzasadnienia.
Co dokładnie zwalnia w pracy użytkownika?
Zgłoszenie „system działa wolno” warto zamienić na opis zadania: otwarcie listy zamówień, zapis formularza, wyszukanie produktu albo przygotowanie raportu. Zapisz, kiedy występuje problem, kogo dotyczy i czy pojawił się po zmianie aplikacji, wzroście ruchu lub zwiększeniu ilości danych. To pomaga odtworzyć sytuację, choć samo zbieżne wystąpienie dwóch zdarzeń nie rozstrzyga przyczyny.
Wykonawca powinien prześledzić tę czynność od kliknięcia do wyniku na ekranie. Część opóźnienia może powstawać w przeglądarce lub połączeniu sieciowym. Jeśli czeka sam serwer, trzeba rozdzielić czas pracy aplikacji, bazy danych i zewnętrznych usług. Bez tego łatwo zapłacić za rozbudowę elementu, który nie odpowiada za problem.
W raporcie potrzebne są czas odpowiedzi, natężenie ruchu, błędy oraz stopień wykorzystania zasobów. To cztery podstawowe obszary opisane w podręczniku monitorowania Google SRE. Ważna jest także poprawność wyniku: szybka odpowiedź z błędem nie oznacza, że pracownik wykonał zadanie.
Ile żądań na sekundę musi obsłużyć aplikacja?
Żądanie to pojedyncze wywołanie serwera, na przykład pobranie danych do tabeli. Jedna czynność użytkownika może wymagać kilku takich wywołań. Dlatego liczba żądań na sekundę, oznaczana jako RPS, nie jest liczbą użytkowników ani zakończonych zamówień.
Do planowania wydajności potrzebny jest opis rzeczywistego ruchu: ile osób równocześnie pracuje, co robią i jak zmienia się obciążenie w godzinach szczytu. Test prostego komunikatu „serwer działa” nie mówi, ile zamówień uda się zapisać wraz ze sprawdzeniem uprawnień, stanów magazynowych i połączeń z innymi systemami.
Jeśli wykonawca przedstawia wynik testu, poproś o zakres pomiaru. Powinno być jasne, czy wynik dotyczy jednego procesu aplikacji, jednego serwera czy wielu serwerów łącznie; jakie dane i funkcje testowano; ile operacji zakończyło się poprawnie oraz jaki był czas odpowiedzi. Potrzebny jest też koszt środowiska, na którym uzyskano wynik. Bez tych informacji trudno wykorzystać liczbę RPS do decyzji o budżecie.
Co poprawić przed zwiększeniem liczby serwerów?
Pomiary powinny wskazać konkretny zakres prac. Dokumentacja optymalizacji Django zaleca najpierw ustalić cel i zbadać działanie aplikacji. Zmiana narzędzi lub wersji oprogramowania wymaga sprawdzenia efektu w danym systemie.
Pobieranie i przetwarzanie danych
Przy wolnej liście zamówień warto sprawdzić, ile danych aplikacja pobiera i ile razy pyta o nie bazę. Może odczytywać całą historię, choć użytkownik widzi tylko jej fragment, albo wykonywać osobne zapytanie dla każdego wiersza. Zalecenia Django dotyczące bazy danych obejmują pomiar zapytań, ograniczanie zbędnych odczytów i dobór indeksów, czyli struktur ułatwiających wyszukiwanie.
Przy odbiorze takiej poprawki poproś wykonawcę o wskazanie zmienionych odczytów lub obliczeń i pokazanie efektu przy tej samej czynności użytkownika.
Przechowywanie gotowych wyników
Cache, czyli pamięć podręczna, pozwala ponownie wykorzystać wcześniej pobrany lub obliczony wynik. Może pomóc tam, gdzie wiele osób odczytuje podobne dane, a ich ponowne przygotowanie jest kosztowne. Trzeba jednak ustalić, jak długo wynik może pozostawać nieaktualny i kiedy zostanie odświeżony. Opis wzorca cache-aside Microsoft wyjaśnia te ograniczenia.
W raporcie historycznym dopuszczalne opóźnienie aktualizacji może być inne niż przy sprawdzaniu dostępności produktu przed sprzedażą. Decyzja o pamięci podręcznej musi więc uwzględniać skutki pokazania starej wartości. W kosztach pozostają również utrzymanie dodatkowej usługi i obsługa sytuacji, gdy wynik trzeba przygotować od nowa.
Oddzielenie zadań, na które można poczekać
Przygotowanie dużego eksportu może odbywać się w tle: użytkownik zleca zadanie, a po zakończeniu otrzymuje plik. Takie rozwiązanie ma sens, jeśli nie potrzebuje wyniku od razu. Trzeba zapewnić widoczny status, informację o błędzie i możliwość bezpiecznego ponowienia.
Szybkie przyjęcie zadania do kolejki nie oznacza jego szybkiego wykonania. Jeśli przez dłuższy czas zadania napływają szybciej, niż są przetwarzane, kolejka będzie rosła, a wraz z nią czas oczekiwania. Przy odbiorze tej zmiany mierz więc również czas od zlecenia do gotowego wyniku. Czynności wymagające natychmiastowego potwierdzenia, takie jak rozstrzygnięcie, czy rezerwacja została zapisana, potrzebują osobnego uzgodnienia.
Kiedy rozbudowa serwerów ma uzasadnienie?
Zwiększenie zasobów ma sens, gdy pomiary wskazują, że ich brak ogranicza wykonywanie potrzebnych operacji. Można rozważyć mocniejszy serwer albo uruchomienie dodatkowych kopii aplikacji i rozdzielenie między nie ruchu. Trzeba sprawdzić, czy pozostałe części systemu przyjmą większe obciążenie.
Jeśli wszystkie kopie korzystają z tej samej przeciążonej bazy danych, dodanie kolejnych nie usuwa tego ograniczenia. Podobnie większa moc serwera aplikacji sama nie skróci oczekiwania na wolną odpowiedź zewnętrznej usługi. Możliwą korzyść powinien potwierdzić test całego potrzebnego procesu.
Przed akceptacją wyceny porównaj warianty przy tym samym celu: jak szybko i z jaką liczbą błędów aplikacja ma wykonywać wskazane zadania przy oczekiwanym ruchu. Obok kosztu wdrożenia uwzględnij miesięczne utrzymanie, pracę potrzebną do obsługi dodatkowych usług oraz sposób ograniczenia wydatków po spadku ruchu. Automatyczne dokładanie zasobów również wymaga uzgodnionego limitu kosztów i reakcji po jego osiągnięciu.
Czy trzeba zmienić Django lub Flask na FastAPI?
Sama informacja, że aplikacja powstała w Django albo Flask, nie uzasadnia jej przepisania. Są to narzędzia do budowania aplikacji webowych. Zmiana na inne narzędzie, takie jak FastAPI, powinna odpowiadać na zmierzone ograniczenie i uwzględniać koszt odtworzenia funkcji, testów oraz późniejszego utrzymania.
Często proponowanym rozwiązaniem jest asynchroniczna obsługa: program może zajmować się innymi zadaniami, kiedy czeka na dane. Pomaga to wykorzystać czas oczekiwania, ale samo w sobie nie przyspiesza ciężkich obliczeń. Wykonywanie takich obliczeń jednocześnie na kilku rdzeniach jest innym mechanizmem, który wymaga odpowiedniego podziału pracy. Różnicę wyjaśnia dokumentacja FastAPI.
Django również obsługuje kod asynchroniczny, choć korzyści zależą od sposobu uruchomienia aplikacji i używanych bibliotek. Warto zacząć od sprawdzenia możliwości obecnego systemu. Jeśli przebudowa wybranego fragmentu okaże się uzasadniona, jej zakres powinien wynikać z pomiaru, a nie z rankingu popularności technologii.
Jak sprawdzić efekt i odebrać pracę wykonawcy?
Przed zmianą uzgodnij scenariusz testu: czynności użytkowników, ilość danych, jednoczesny ruch oraz warunki działania połączeń z innymi systemami. Po zmianie powtórz go w porównywalnym środowisku. Dokumentacja testów obciążeniowych k6 zaleca odtworzenie zwykłej pracy użytkowników i obserwowanie systemu przez czas pozwalający zobaczyć jego zachowanie pod obciążeniem. Dla Twojej firmy potrzebny może być także osobny scenariusz szczytu sprzedaży.
Nie ograniczaj odbioru do średniego czasu. Przydatny jest na przykład p95 czasu poprawnie zakończonych operacji: 95% z nich mieści się w podanym czasie. Pozostałe mogą trwać dłużej, dlatego obok tego wyniku trzeba ocenić błędy i najdłuższe opóźnienia. Cel czasowy powinien wynikać z zadania: zapis formularza i przygotowanie dużego raportu mogą mieć różne wymagania.
Raport odbioru powinien pokazać wynik przed zmianą i po niej, warunki obu pomiarów, pozostałe ograniczenia oraz koszt utrzymania rozwiązania. Przy pamięci podręcznej warto sprawdzić także pracę bez zapisanych wyników, a przy zadaniach w tle - czas oczekiwania na ich zakończenie. Ustal również, kto zareaguje na pogorszenie działania po wdrożeniu i jak można wrócić do poprzedniej wersji.
Do pierwszej rozmowy wystarczy opis problematycznych czynności, przykłady ich wystąpienia i informacja o planowanym wzroście ruchu. Jeśli zlecasz rozwój i utrzymanie istniejącej aplikacji, uzgodnij na początek diagnozę z propozycją zakresu prac i sposobem sprawdzenia wyniku. Taki materiał pozwala zdecydować, za którą zmianę warto zapłacić.


