Długi czas oczekiwania na odpowiedź serwera Apache 2.2 (LAMPA Gentoo)

9

Niedawno przeniosłem stronę klienta (za pomocą CMS Concrete5) na VPS z Gentoo, Apache 2.2, PHP5 i MySQL 5 i zauważyłem, że czasy odpowiedzi Apache są dość złe (było tak samo na starym serwerze) , czasami znacznie do 8-9 sekund, ale częściej od 300 ms do 3 sekund (do 300 ms nie mam nic przeciwko). Wiem, że to nie jest opóźnienie sieciowe, ponieważ serwer ma ping (z mojej lokalizacji) około 30ms.

Oto przykład czasów (widać, że po początkowym oczekiwaniu jest to zgrabne):

Oś czasu panelu Firebug Net

Używam APC (chociaż nie jestem pewien, czy to działa poprawnie ) i SuExec. Moduły Apache to:

 core_module (static)
 authn_file_module (static)
 authn_default_module (static)
 authz_host_module (static)
 authz_groupfile_module (static)
 authz_user_module (static)
 authz_default_module (static)
 auth_basic_module (static)
 include_module (static)
 filter_module (static)
 deflate_module (static)
 log_config_module (static)
 env_module (static)
 expires_module (static)
 headers_module (static)
 setenvif_module (static)
 version_module (static)
 ssl_module (static)
 mpm_prefork_module (static)
 http_module (static)
 mime_module (static)
 status_module (static)
 autoindex_module (static)
 asis_module (static)
 info_module (static)
 suexec_module (static)
 cgi_module (static)
 negotiation_module (static)
 dir_module (static)
 actions_module (static)
 userdir_module (static)
 alias_module (static)
 rewrite_module (static)
 so_module (static)
 suphp_module (shared)

a moduły PHP to:

bcmath
calendar
ctype
curl
db
dbase
domxml
exif
ftp
gd
gettext
iconv
imap
mbstring
mcrypt
mime_magic
mysql
openssl
overload
pcre
posix
session
standard
sysvsem
sysvshm
tokenizer
xml
xslt
zlib

Mam włączony gzip dla wszystkich odpowiednich plików.

Apache działa przy użyciu prefork, a ustawienia w httpd.conf to:

<IfModule prefork.c>
StartServers         10
MinSpareServers      10
MaxSpareServers      20
MaxClients           250
MaxRequestsPerChild  4000
</IfModule>

HostnameLookups Off

Zauważyłem, że strony, które (jak sądzę) są obciążone bazą danych, takie jak Dashboard CMS, są zwykle wolniejsze. Pomyślałem, że to może oznaczać, że MySQL można zoptymalizować. Zastanawiałem się również nad modułami Apache - mylę się między mod_php5, mod_cgi, mod_fastcgi itp. Itd. - W sieci jest sprzeczna rada co do tego, który najlepiej użyć.

Oto wynik MySQLTuner :

-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.0.44-log
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: -Archive -BDB -Federated -InnoDB -ISAM -NDBCluster
[--] Data in MyISAM tables: 35M (Tables: 161)
[!!] Total fragmented tables: 15

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 3d 21h 44m 16s (293K q [0.868 qps], 1K conn, TX: 135M, RX: 90M)
[--] Reads / Writes: 99% / 1%
[--] Total buffers: 58.0M global + 1.6M per thread (100 max threads)
[!!] Maximum possible memory usage: 219.7M (93% of installed RAM)
[OK] Slow queries: 0% (0/293K)
[OK] Highest usage of available connections: 2% (2/100)
[OK] Key buffer size / total MyISAM indexes: 16.0M/20.9M
[OK] Key buffer hit rate: 99.6% (5M cached / 21K reads)
[!!] Query cache is disabled
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 3K sorts)
[!!] Temporary tables created on disk: 47% (2K on disk / 5K total)
[!!] Thread cache is disabled
[!!] Table cache hit rate: 6% (64 open / 1K opened)
[OK] Open file limit used: 12% (128/1K)
[OK] Table locks acquired immediately: 100% (356K immediate / 356K locks)

-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Reduce your overall MySQL memory footprint for system stability
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Set thread_cache_size to 4 as a starting value
    Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
  *** MySQL's maximum memory usage is dangerously high ***
  *** Add RAM before increasing MySQL buffer variables ***
    query_cache_size (>= 8M)
    tmp_table_size (> 32M)
    max_heap_table_size (> 16M)
    thread_cache_size (start at 4)
    table_cache (> 64)

Zauważyłem, że gdy załadowano stronę obciążoną DB, użycie procesora wzrosło o 57% (używając góry) - co sugeruje, że albo źle zoptymalizowano MySQL, albo buforowanie jest absolutnie konieczne, aby przyspieszyć tę konfigurację.

Każda pomoc będzie mile widziana!

melat0nin
źródło
2
Tylko myśl: czy HostnameLookupw konfiguracji dziennika jest włączona? Jeśli tak, wyszukiwanie DNS żądającego klienta, który ma zostać dodany do dziennika dostępu, może być bardzo wolne (lub pierwszy serwer DNS nawet przekroczy limit czasu), co może spowolnić pełne żądanie.
jCoder
Jest wyłączony - dodam to do oryginalnego postu
melat0nin 18.10.11
Jeśli są to tylko żądania dotyczące PHP. Sprawdź fragmentację w APC. Powinieneś również ściśle monitorować wykorzystanie zasobów; Czy serwer wykorzystuje wszystkie swoje zasoby, czy też pracuje na biegu jałowym?
Kvisle
Już jestem (patrz OP) :)
melat0nin 18.10.11
Przepraszam za to :) - zaktualizowałem mój komentarz; Czy sprawdziłeś, czy są to tylko żądania PHP, czy też inne? Czy serwer jest bezczynny lub zajęty? Czy APC jest rozdrobniony czy nie? Ile pamięci jest „buforowane” w porównaniu do innych rzeczy?
Kvisle,

Odpowiedzi:

14

Czy dokładnie wiesz, na czym polegają procesy robocze apache? Spróbuj tego, aby zobaczyć:

mkdir /strace; ps auxw | grep httpd | awk '{print"-p " $2}' | xargs strace -o /strace/strace.log -ff -s4096 -r

Załaduj kilka nowych (tj. Nie lokalnie buforowanych) stron w przeglądarce, CTRL + C, aby zatrzymać strace, a następnie posortuj strace.logs według czasu spędzonego na każdym wywołaniu:

for i in `ls /strace/*`; do echo $i; cat $i | cut -c11-17 | sort -rn | head; done

Przeglądaj dowolne strace.logs z ponad 1,0 sekundowymi wywołaniami i szukaj według czasu z wyjścia poprzedniego polecenia. To wskaże ci dokładnie ten krok, na którym się zawieszają.

Czy z kolei masz zainstalowaną zaporę ogniową, taką jak CSF? Ten sam problem widziałem na VPS. Podczas debugowania procesów httpd za pomocą strace trwało to do 5 sekund lub więcej w przypadku połączeń gettimeofday. Dziwnie zawęziłem to do CSF, który próbował filtrować interfejs venet0, interfejs pętli zwrotnej w kontenerach OpenVZ lub Virtuozzo. Ustawienie tego parametru w /etc/csf/csf.conf głównie dla mnie naprawiło:

"ETH_DEVICE_SKIP = "venet0,lo"

Mówię głównie dlatego, że czasami wciąż jest 500-1000 ms, czekam na ustanowienie połączeń, ale to duża poprawa od 5000+.

reflexiv
źródło
1
Dzięki za odpowiedź! Ostatecznie wszystko wyglądało na załatwione, kiedy APC działało poprawnie - strona jest teraz dość zgrabna. +1 za doskonałe instrukcje i zanotuję je na wypadek, gdyby znów spotkałem się z czymś takim.
melat0nin 12.12.11
3

Oto doskonały podkład / przegląd do rozwiązywania tego rodzaju problemów za pomocą strace.

Maximum possible memory usage: 219.7M (93% of installed RAM)

To musi być tanie urządzenie VPS?

  • Możesz chcieć zmniejszyć swoje ustawienia MySQL
  • Dostrój Apache, aby zmniejszyć liczbę rozwidleń httpd
  • Sprawdź, czy możesz włączyć zamianę
  • Czy APC jest ustawione na automatyczne buforowanie kodów operacji? Sprawdź za pomocą skryptu „apc.php” dystrybuowanego wraz z apc.
cienki lód
źródło
3

Musisz rozdzielić sieć, apache, mysql i php jako źródła opóźnień.

Jeśli możesz szybko pobrać obraz z apache (bardzo mało czasu do pierwszego bajtu), wtedy sieć i apache są zazwyczaj w porządku.

Jeśli możesz wyciągnąć stronę za pomocą instrukcji phpinfo (), to zwykle PHP jest w porządku (może wymagać kilku poprawek).

Jeśli napiszesz prosty test połączenia DB i jest on szybki, wtedy ta warstwa jest zwykle w porządku.

Na koniec pociągnij stronę aplikacji. Jeśli jest wolny, problem dotyczy przetwarzania aplikacji. Chociaż strojenie może pomóc, jest to o wiele trudniejsze do rozwiązania.

Bez profilowania aplikacji znalezienie problemu może być trudne. Narzędzia takie jak NewRelic mogą pomóc w rozwiązaniu tego problemu, ale nie są lekarstwem.

Czy Twoja aplikacja ma jakieś wewnętrzne debugowanie, aby pokazać, gdzie spędza się czas?

jeffatrackaid
źródło
0

Sugeruję dodanie pomiaru czasu renderowania i sprawdzenie, ile czasu zajmuje serwerowi renderowanie czystej strony HTML. Wtedy wiesz, czy jest w CMS, czy gdzie indziej. Założę się, że moje 2 centy to nie twoja konfiguracja serwera. / maddin

maddin
źródło
Czy możesz zasugerować metodę pomiaru czasu renderowania? Czy panel Net Firebuga na statycznej stronie HTML jest wystarczający?
melat0nin