Skalbarhet, eller hur mycket server behöver jag för min webbapplikation?

Prestanda är viktigt på webben. Om din webbtjänst eller webbplats är bara en aning långsam, kommer användarna sticka därifrån. Det har skrivits en del om hur prestanda påverkar besökarna, exempelvis av Jakob Nielsen och Stoyan Stefanov. Vet du hur länge dina besökare får vänta på din webbplats, och hur du snabbar upp den?

Du bör inte fundera så mycket på prestanda och skalbarhet från början; du vet ju inte hur många besökare du kommer få. Då är det bättre att fokusera på att över huvud taget komma ut på marknaden, och sedan hoppas att du får så många besökare att prestanda blir ett problem. Övervaka belastningen och laddningstiderna och förbättra prestanda så fort det börjar bli segt. Inte tidigare (om du inte har för lite att göra och för mycket pengar).

För enkelhets skull utgår jag i resten av artikeln från att du har en enkel webbapplikation som körs på en Apache-webbserver med PHP och MySQL. Vi tar en titt på den enklaste arkitekturen, där allt körs på samma server:

Apache+MySQL-arkitektur

På webbserven finns ett antal Apache-processer som lyssnar efter förfrågningar från webbläsarna. (Om förfrågningarna blir fler än antal processer, bildas en kö där de tas om hand successivt. Om kön blir för lång får besökarna felmeddelanden.) Varje process levererar statiska filer som bilder, stilmallar och Javascript, men exekverar också PHP-skript och levererar resultatet till webbläsaren. Filerna ligger på hårddisken, som processerna får turas om att läsa från.

På samma server körs också en MySQL-databas, som processerna skickar SQL-frågor till. Databasen analyserar och exekverar frågorna, plockar fram det data som efterfrågats och levererar det.

När du nu har konstaterat att du behöver förbättra prestanda gör du så här, om och om igen:

  1. Mät prestanda i hela kedjan och hitta den största flaskhalsen.
  2. Förbättra bara den största flaskhalsen, och mät effekterna efteråt. Blev det bättre, grattis! Om det inte blev bättre, återställ och försök på ett annat sätt.

Om du inte följer den här metoden kommer du nog bli galen förr eller senare. Arkitekturer med många led och parallella processer är så komplexa och svåröverskådliga att du måste gå metodiskt fram för att vara säker på att dina ändringar faktiskt är förbättringar. Dessutom riskerar du annars att lägga onödigt mycket tid och pengar på prestandaförbättringar som inte får någon effekt.

Var flaskhalsarna sitter beror på vilken typ av belastning du har, hur din webbapplikation fungerar och mycket annat. Men här är några typfall av flaskhalsar:

  • Överföring av filer från webbservern till webbläsaren
  • Exekvering av PHP-skript
  • Exekvering av databasfrågor
  • Rendering av html-sidor med CSS-regler
  • Exekvering av Javascript
  • Hämtning av externa widgets och annonser

Så, hur åtgärdar vi dem? Jag går igenom några enkla tips för de allra vanligaste, nämligen de tre första.

Överföring av filer från webbservern till webbläsaren: Du kan exempelvis dela upp webbservern så att vissa processer levererar statiska filer såsom bilder, CSS och Javascript, och andra exekverar PHP-skript.

Statiska filer kan nämligen levereras många gånger snabbare än ett PHP-skript exekveras, och en Apache-process som kan exekvera PHP-skript kräver mycket mer minne än en som ”bara” levererar filer. Alltså kan du köra många fler processer som levererar filer än som kör PHP, vilket leder till högre prestanda för besökaren. (Titta exempelvis på Varnish som ett komplement till Apache.)

Statiska filer kan dessutom komprimeras för att ta mindre utrymme och därmed gå snabbare att överföra från webbservern till webbläsaren. Även en liten minskning i storlek kan ge stora tidsvinster om filen överförs tusentals gånger per sekund. Komprimering kan ske både med en så kallad minifierare för textfiler (exempelvis YUI Compressor) och genom att aktivera Gzip-komprimering i Apache. Bildfiler kan också komprimeras med Smush.it.

Exekvering av PHP-skript: PHP-exekvering kan snabbas upp flera gånger genom att aktivera en PHP-accelerator såsom APC. När PHP-skript ska köras, kompileras de nämligen av servern varje gång, och resultatet slängs bort. APC ser till att cacha resultatet av kompileringen så att det inte behöver göras om vid varje anrop.

Du kan också se om det går att skriva om din PHP-kod på ett mer effektivt sätt. Undersök vilka delar av koden som tar längst tid och skriv om dem. Det här är dock svårare än det låter.

Självklart exekveras PHP-skript också snabbare om webbserverns processor är snabbare (om de inte är så att PHP-skriptets flaskhals är när det läser från hårddisk eller liknande).

Exekvering av databasfrågor: Eftersom man kan hämta samma data från databasen med helt olika databasfrågor, är det absolut värt ett försök att skriva om dem. Undersök vilka frågor som tar mest tid och se om det finns några alternativ som du kan prova. (Exempelvis har jag själv delat upp en ganska komplex fråga i 30 enkla, och exekveringstiden minskade flera gånger!) Du kanske också behöver lägga till fler index för att snabba upp frågorna?

Använd en cache-server som Memcached för att lagra exempelvis resultatet av tidskrävande databasfrågor i minnet och få fram dem blixtsnabbt.

I extremfall kanske du till och med ska fundera på att byta från en ”vanlig” databas som MySQL till en som är bättre på att hantera enorma mängder besökare eller data. Exempelvis kör Google och Facebook helt andra databaser som gemensamt brukar gå under benämningen NoSQL. Titta exempelvis på Redis, MongoDB eller Cassandra. Men observera att du måste göra om hela databasmodellen och lära dig att tänka helt annorlunda.

Generella tips: Minne är vanligtvis ett enkelt sätt att snabba upp en server. Ju mer minne servern har, desto fler Apache-processer kan köras för att ta emot förfrågningar från webbläsarna. Ju mer minne, desto mer kan MySQL-servern cacha och slippa läsa från disk.

Istället för att samma server gör flera saker kan du förstås dela upp det så att olika servrar sköter olika uppgifter. Exempelvis kan en server exekvera PHP-skript, en annan leverera statiska filer och en tredje köra MySQL. Det här går att göra hur komplext som helst, läs exempelvis om Lunarstorms gamla serverarkitektur.

Du måste kanske heller inte köra Apache, utan kan använda Nginx istället. Det är en ganska ny webbserver som brukar vara mycket snabbare och används av fler och fler stora webbplatser.

Läs mer

Det finns mycket att lära om hur du kan göra din webbplats snabbare: