Etikettarkiv: apache

WordPress prestanda 101

Under Sweden Social Web Camp så försökte jag på kort under en session tid förklara hur man kan analysera och hitta flaskhalsar i WordPress gällande prestanda. Så därför försökte jag här sammanfatta det jag pratade om på några rader.

Först och främst så bör du stänga av alla plugins och då se om prestandan fortfarande är dålig, för tyvärr finns det många dåliga plugins (se här då Computer Sweden intervjuade mig och Nikke, år 2009).

Okej, nästa grej att testa är att slå på något cache-plugin i form av W3 Total Cache eller WP Super Cache. Du kan även testa att ”städa upp” i databasen då många plugins lägger temporär eller onödig information i databasen (kommentera om du vet något plugin som gör detta).

Använder du ett cache-plugin så bör du även installera memcached samt titta i källkoden längst ner på sidan hur många SQL-anrop som cachas, exempelvis (skriver WP Super Cache också ut detta?):

Object Caching 730/765 objects using memcached

En annan grej man kan testa är att använda strace direkt från kommandotolken i Linux tillsammans med PHP, ungefär så här:

$ cd /min/blogg/

$ strace php index.php

Så får du lite loggrader utspottade på skärmen och om det står still länge på ett ställe så ser du exakt vad som händer på den raden. Samt så bör du även testa Xdebug så kan berätta exakt vilken rad i PHP-koden som går långsamt, tar lite tid att installera och använda.

Du kan även titta i MySQL:s slow-log som kan aktiveras på eller hittas i /etc/mysql/my.cnf (sök efter log_slow_queries).

Sist men inte minst det som jag brukar göra är att lägga upp Varnish som en front-end proxy framför Apache exempelvis, detta är en helt mer eller mindre transparent lösning. Kom även ihåg att Apache slukar massor av minne jämfört med Nginx som istället kan användas till memcached. Detta är nog det bästa tipset jag kan ge samt att testa använda ett CDN.

Sen finns det så klart mycket man kan göra på själva sidorna som WordPress spottar ut (sprites, javascript etc), men det är utanför detta blogginlägg.

Uppdatering: Glömde skriva två saker som jag nämnde på sessionen, dels är det att använda sig av en OP-code cache typ APC eller eAccelerator samt så kan även URL-strukturen i WordPress slöa ner prestandan.

Snabb guide till Varnish

Fick en förfrågan från John Angelmo (@veidit) att skriva lite om den supergrymma front-end cachen Varnish. Varnish utvecklas till stor del av företaget Linpro från Norge med hjälp av den danske FreeBSD-utvecklaren Poul-Henning Kamp.

I Sverige är Varnish populärt och används av exempelvis Aftonbladet och SvD. Varnish har en mängd intressanta features och ett mycket kraftfullt konfigurationsspråk som påminner om C.

Använder du Ubuntu som jag gör så är det bara att installera via APT:

$ sudo apt-get install varnish

Standard så lyssnar varnish på TCP port 6081 och skickar vidare förfrågningarna till port 8080 där du förväntas ha din webbserver såsom Apache eller nginx.

Konfigurationsfilen för varnish återhittas i katalogen /etc/varnish/ med filnamnet default.vcl. VCL är också benämningen på det konfigurationsspråk som används som stödjer bla inline C. Se denna PDf-presentation av PHK för mer info.

Det viktiga vi behöver känna till är hur vi pekar ut vårat backend och vilka filer vi vill lagra i cachen. I mitt fall så valde jag Varnish för att Apache drog på tok för mycket minne då exempelvis bara bilder, css och annan statisk information skulle visas.

Nedan konfigurationsfil pekar först ut backend, sedan så sätter den X-Forwarded-For http-headern för att underlägga loggningen i Apache.

Sen så defineras vad som skall chachas.


backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
remove req.http.X-Forwarded-For;
set    req.http.X-Forwarded-For = client.ip;
if (req.url ~ "^/css" || req.url ~ "^/images" || req.url ~ "^/facebox" || req.url ~ "^/avatars") {
return(lookup);
}
if (req.request != "GET" && req.request != "HEAD") {
return(pipe);
}
if (req.url ~ "^/feedlist.php" || req.url ~ "^/removefeed.php" || req.url ~ "^/feeds.php" || req.url ~ "^/addfeeds" || req.url ~ "^/42it" || req.url ~ "^/login.php"
|| req.url ~ "^/admin" || req.url ~ "^/settings" || req.url ~ "^/js/tinymce/" ) {
return(pipe);
}
if (req.url ~ "\.(jpg|jpeg|gif|png|tiff|tif|svg|swf|ico|css|vsd|doc|ppt|pps|xls|pdf|mp3|mp4|m4a|ogg|mov|avi|wmv|sxw|zip|gz|bz2|tgz|tar|rar|odc|odb|odf|odg|odi|odp|o
ds|odt|sxc|sxd|sxi|sxw|dmg|torrent|deb|msi|iso|rpm)$") {
return(lookup);
}
}

sub vcl_hash {
set req.hash += req.http.cookie;
}

Uppdatering: Varför jag ibland måste använda Varnish tillsammans med Apache istället för mitt förstahandsval Nginx är pga de invecklade .htacess-filer jag skapat.

Operation driftsäkerhet och hastighet

Just nu jobbar jag på att försöka få till en bättre driftsäkerhet samt hastighet på mina webbplatser. Detta innebär bl.a att tjänster flyttas om mellan mina minst sex servrar och att mjukvaror såsom Apache slängs ut till förmån för Nginx och Lighttpd.

Jag försöker minska antalet komponenter som kan gå fel och försöker införskaffa viss överkapacitet istället för att alltid ha lite för lite som det varit tidigare.

Detta kommer troligtvis att resultera i mindre brandsläckning och mer tid till utveckling av nya grymma tjänster. Har även för avsikt att sälja av ett antal mindre tjänster såsom TweetValue via exempelvis Flippa.com

Att skriva bra kod

På senare tid så lägger jag mer tid och kraft till att skriva bra (snygg) och snabb kod. Att optimera sin PHP-kod kan spara många millisekunder i exekveringen. Vad pratar jag om då? Jo det finns några bra tips:

Kolla igenom all din kod med xdebug för att hitta långsamma exekveringar/funktioner. Och använd med fördel memcached, Sphinx och eAccelerator. Kasta bort Apache och titta istället på nginx och lighttpd. Jag har tidigare skrivit om hur du optimerar MySQL.

Det lönar sig att göra rätt från början!

Bloggys infrastruktur

Tänkte beskriva lite om hur Bloggy är uppbyggt rent tekniskt. En förfrågan till Bloggy går ungefär igenom följande lager:

MySQL <- Sphinx <- Memcached <- Apache <- Varnishd

Varnish är en högpresterande webb frontend-proxy utvecklat av ett norskt företag och används  exempelvis av Aftonbladet. Detta går att utläsa genom HTTP-headern X-Varnish.

Denna frontend-cache används för att hantera alla statiska filer såsom CSS och bilder. Apache behöver jag inte skriva så mycket om men sedan kommer en intressant del och det är memcached som är utvecklat av Facebook.

De flesta SQL-frågor går genom memcached för att cachas ett antal sekunder, varje SQL-fråga är noggrant studerad hur länge den behöver cachas.

Sphinx är också en intressant del eftersom den gör att fulltextsökningar mot olika tabeller i MySQL-databasen. Sphinx tar hand om runt 40 sökningar i sekunden.

Sedan så kommer MySQL som hanterar allt annat som inte fångas upp av något av ovanstående system. Alla frågor har optimerats så att filsorteringar (file sort) och dylikt används minimalt. Jag har även tidigare (2007) bloggat om hur du kan optimera din MySQL databas.

Felsökning Apache

En av mina servrar börjar gå på knäna och antalet Apache-processer låg runt 200 stycken vilket är det maxtak jag definerat med ”RLimitNPROC 200 200″ i config-filen för Apache.

Jag började min felsökning  och som vanligt så undersökte jag MySQL-datbasen vad det kan vara som kan gå långsamt men hittade inget där (show processlist samt mysql-slow.log).

Men efter lite tips från Webmasters Network så la jag till ExtendedStatus On och där uppenbarade det sig vilken virtuell host som tog all kapacitet och vilket script.

Så jag la till en ”LIMIT 1″ i slutet på en SQL-update och la en bild på ett CDN som ofta hämtades och vips så sjönk antelet Apache-processer till enbart 50 stycken:

Total accesses: 28353 – Total Traffic: 137.8 MB
CPU Usage: u6.84 s1.18 cu.39 cs0 – .249% CPU load
8.39 requests/sec – 41.7 kB/second – 5095 B/request
45 requests currently being processed, 7 idle workers