Chcę zrozumieć niektóre problemy z wydajnością serwera, które widzę w przypadku (dla nas) mocno obciążonego serwera WWW. Środowisko jest następujące:
- Debian Lenny (wszystkie stabilne pakiety + załatane do aktualizacji bezpieczeństwa)
- Apache 2.2.9
- PHP 5.2.6
- Duża instancja Amazon EC2
Zachowanie, które widzimy, polega na tym, że sieć zazwyczaj reaguje szybko, ale z niewielkim opóźnieniem, aby rozpocząć obsługę żądania - czasami ułamek sekundy, a czasem 2-3 sekundy w szczytowym okresie użytkowania. Rzeczywiste obciążenie serwera jest zgłaszane jako bardzo wysokie - często 10.xx lub 20.xx, jak podaje top
. Co więcej, uruchamianie innych rzeczy na serwerze w tych czasach (nawet vi
) jest bardzo wolne, więc obciążenie zdecydowanie tam jest. Dziwne, że Apache pozostaje bardzo responsywny, poza początkowym opóźnieniem.
Apache skonfigurowaliśmy w następujący sposób, używając prefork:
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
I KeepAlive jako:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
Patrząc na stronę statusu serwera, nawet w czasach dużego obciążenia rzadko uderzamy w limit klienta, zwykle obsługując od 80 do 100 żądań i wiele z nich w stanie podtrzymania. To każe mi wykluczyć powolność początkowego żądania jako „czekanie na moduł obsługi”, ale mogę się mylić.
Monitorowanie CloudWatch w Amazon mówi mi, że nawet gdy nasz system operacyjny zgłasza obciążenie> 15, użycie procesora przez instancję wynosi od 75 do 80%.
Przykładowe dane wyjściowe z top
:
top - 15:47:06 up 31 days, 1:38, 8 users, load average: 11.46, 7.10, 6.56
Tasks: 221 total, 28 running, 193 sleeping, 0 stopped, 0 zombie
Cpu(s): 66.9%us, 22.1%sy, 0.0%ni, 2.6%id, 3.1%wa, 0.0%hi, 0.7%si, 4.5%st
Mem: 7871900k total, 7850624k used, 21276k free, 68728k buffers
Swap: 0k total, 0k used, 0k free, 3750664k cached
Większość procesów wygląda następująco:
24720 www-data 15 0 202m 26m 4412 S 9 0.3 0:02.97 apache2
24530 www-data 15 0 212m 35m 4544 S 7 0.5 0:03.05 apache2
24846 www-data 15 0 209m 33m 4420 S 7 0.4 0:01.03 apache2
24083 www-data 15 0 211m 35m 4484 S 7 0.5 0:07.14 apache2
24615 www-data 15 0 212m 35m 4404 S 7 0.5 0:02.89 apache2
Przykładowe dane wyjściowe vmstat
w tym samym czasie co powyżej:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
8 0 0 215084 68908 3774864 0 0 154 228 5 7 32 12 42 9
6 21 0 198948 68936 3775740 0 0 676 2363 4022 1047 56 16 9 15
23 0 0 169460 68936 3776356 0 0 432 1372 3762 835 76 21 0 0
23 1 0 140412 68936 3776648 0 0 280 0 3157 827 70 25 0 0
20 1 0 115892 68936 3776792 0 0 188 8 2802 532 68 24 0 0
6 1 0 133368 68936 3777780 0 0 752 71 3501 878 67 29 0 1
0 1 0 146656 68944 3778064 0 0 308 2052 3312 850 38 17 19 24
2 0 0 202104 68952 3778140 0 0 28 90 2617 700 44 13 33 5
9 0 0 188960 68956 3778200 0 0 8 0 2226 475 59 17 6 2
3 0 0 166364 68956 3778252 0 0 0 21 2288 386 65 19 1 0
I na koniec wynik z Apache server-status
:
Server uptime: 31 days 2 hours 18 minutes 31 seconds
Total accesses: 60102946 - Total Traffic: 974.5 GB
CPU Usage: u209.62 s75.19 cu0 cs0 - .0106% CPU load
22.4 requests/sec - 380.3 kB/second - 17.0 kB/request
107 requests currently being processed, 6 idle workers
C.KKKW..KWWKKWKW.KKKCKK..KKK.KKKK.KK._WK.K.K.KKKKK.K.R.KK..C.C.K
K.C.K..WK_K..KKW_CK.WK..W.KKKWKCKCKW.W_KKKKK.KKWKKKW._KKK.CKK...
KK_KWKKKWKCKCWKK.KKKCK..........................................
................................................................
Z mojego ograniczonego doświadczenia wyciągam następujące wnioski / pytania:
Możliwe, że zezwalamy na zbyt wiele
KeepAlive
żądańWidzę trochę czasu spędzonego na czekaniu na IO w vmstat, chociaż nie konsekwentnie i nie za dużo (myślę?), Więc nie jestem pewien, czy to jest duże zmartwienie, czy nie, mam mniejsze doświadczenie z vmstat
Również w vmstat widzę w niektórych iteracjach szereg procesów oczekujących na obsłużenie, do czego przypisuję początkowe opóźnienie ładowania strony na naszym serwerze WWW, być może błędnie
Podajemy mieszankę zawartości statycznej (75% lub wyższej) i treści skryptu, a treść skryptu jest często dość intensywna pod względem procesora, dlatego ważne jest znalezienie właściwej równowagi między nimi; długoterminowo chcemy przenieść statykę w inne miejsce, aby zoptymalizować oba serwery, ale nasze oprogramowanie nie jest na to gotowe
Z przyjemnością udzielam dodatkowych informacji, jeśli ktoś ma jakieś pomysły, druga uwaga jest taka, że jest to instalacja produkcyjna o wysokiej dostępności, więc obawiam się poprawiać po poprawce i dlatego sam nie grałem z takimi KeepAlive
wartościami, jak wartość jeszcze.
źródło
Odpowiedzi:
Zacznę od przyznania, że nie mam wiele do czynienia z chmurami - ale na podstawie mojego doświadczenia w innych miejscach powiedziałbym, że ta konfiguracja serwera WWW odzwierciedla dość mały ruch. To, że kolejka jest tak duża, sugeruje, że po prostu nie ma wystarczającej ilości procesora, aby sobie z tym poradzić. Co jeszcze jest w kolejce?
Nie - keeplive wciąż poprawia wydajność, nowoczesne przeglądarki są bardzo inteligentne, kiedy wiedzą, kiedy należy potokować, a kiedy uruchamiać żądania równolegle, chociaż limit czasu 5 sekund jest nadal dość wysoki, a czeka na Ciebie mnóstwo serwerów - chyba że „ MAMY OGROMNE problemy z opóźnieniami, zaleciłbym zmniejszenie tego do 2-3. To powinno skrócić nieco runqueueue.
Jeśli nie masz jeszcze zainstalowanego mod_deflate na serwerze - polecam to zrobić - i dodaj ob_gzhandler () do swoich skryptów PHP. Możesz to zrobić jako automatyczne dodawanie:
(tak, kopresja zużywa więcej procesora - ale powinieneś oszczędzać procesor ogólnie, szybciej usuwając serwery z kolejki / obsługując mniej pakietów TCP - a dodatkowo twoja strona jest szybsza).
Polecam ustawić górną granicę MaxRequestsPerChild - powiedzmy coś w rodzaju 500. To tylko pozwala na pewien obrót w procesach na wypadek, gdybyś miał przeciek pamięci. Twoje procesy httpd wyglądają na OGROMNE - upewnij się, że usunąłeś wszystkie moduły apache, których nie potrzebujesz i upewnij się, że podajesz statyczne treści z dobrymi informacjami o buforowaniu.
Jeśli nadal występują problemy, oznacza to, że problem prawdopodobnie dotyczy kodu PHP (jeśli przełączysz się na używanie fastCGI, powinno to być oczywiste bez większych strat wydajności).
aktualizacja
Jeśli zawartość statyczna nie różni się znacznie na stronach, warto również poeksperymentować z:
również w skryptach PHP.
źródło
Należy rozważyć zainstalowanie asynchronicznego zwrotnego proxy, ponieważ liczba procesów w stanie W jest również dość wysoka. Wydaje się, że procesy Apache spędzają dużo czasu na wysyłaniu treści do powolnych klientów za pośrednictwem sieci, która jest zablokowana. Nginx lub lighttpd jako nakładka na serwer Apache mogą znacznie zredukować liczbę procesów w stanie W. I tak, powinieneś ograniczyć liczbę żądań podtrzymania. Prawdopodobnie warto spróbować wyłączyć Keepalive.
BTW, 107 procesów Apache są zbyt wysokie dla 22 rps, byłem w stanie obsłużyć 100-120 rps przy użyciu tylko 5 procesów Apache. Prawdopodobnie następnym krokiem jest profilowanie aplikacji.
źródło
Masz dwa wiersze w vmstat, które pokazują, że twój czas oczekiwania procesora jest dość wysoki, a wokół nich wykonujesz sporo zapisów (io - bo) i przełączanie kontekstu. Spojrzałbym na to, co pisze bloki i jak wyeliminować to czekanie. Myślę, że największą poprawę można znaleźć w poprawianiu IO dysku. Sprawdź syslog - ustaw, aby zapisywał asynchronicznie. Upewnij się, że pamięć podręczna zapisu kontrolera działa (sprawdź - może być zła bateria).
Keepalive nie powoduje problemów z perfem, oszczędza czas konfiguracji połączenia, jeśli nie korzystasz z pamięci podręcznej z przodu. Możesz nieco podnieść MaxSpareServers, aby w sytuacji kryzysowej nie czekać na wszystkie widelce.
źródło
powinieneś rozważyć wyłączenie Keepalive jako pierwszej próby ...
przy 107 przetworzonych żądaniach utrzymałbym MaxSpareServers wyżej niż ustawiłeś ...
IMHO w długoterminowej nginx jako odwrotny serwer proxy dla treści statycznych powinien być brany pod uwagę
źródło
Pierwsza sugestia: wyłącz Keepalives. Potrzebowałem go tylko wtedy, gdy mogłem zidentyfikować konkretną sytuację, w której wydajność wzrosła, ale ogólnie liczba żądań na sekundę spadła przy włączonej Keepalive.
Druga sugestia: Ustaw MaxRequestsPerChild. I echo symcbean tutaj, to pomoże w przejściu procesu w przypadku wycieku pamięci. 500 jest dobrym punktem wyjścia.
Trzecia sugestia: Zwiększ MaxClients. Obliczeniem typu ballpark jest to (pamięć fizyczna - pamięć używana przez proces inny niż httpd) / rozmiar każdego procesu httpd. W zależności od sposobu kompilacji httpd liczba ta wynosi maks. 255. Używam 250 dla moich publicznych serwerów, aby radzić sobie z Google / Yahoo / MS indeksującymi systemy.
Czwarta sugestia: Zwiększ MaxSpareServers: coś w rodzaju 4-5x MinSpareServers.
Jeśli te sugestie zawiodą, przyjrzałbym się równoważeniu obciążenia za pomocą odwrotnego proxy lub memcache dla DB.
źródło