Med tiden er web-applikationer og webservere blevet mere og mere tunge, både hvad angår brug af processortid og RAM-aftryk. Nye frameworks og CMS’er såsom JBOSS (Java), TYPO3 (PHP) og WordPress (PHP) lægger beslag på voldsomme mængder RAM og stiller derfor store krav til de maskiner, der skal hoste siderne. Optimering af PHP og Java som webplatform er et afsnit for sig, men uanset hvad, kan det være en vanskelig øvelse, der kræver mange eksperimenter, test og gennemgang af logfiler. Jeg vil fokusere på PHP i dette indlæg, men nogle af anbefalingerne kan også bruges på andre server-side teknologier. For PHP’s vedkommende er det grundlæggende problem ofte, at man benytter mod_php kombineret med mpm_prefork. I denne tilstand ligger PHP’s vm i Apache’s process-rum og kræver en masse RAM, samtidig med at der skal én Apache-process til at servicere ét HTTP-kald. Vi begynder også at se en trend i, at der konstant kører Ajax-kald ned til serveren. Hvis man oven i dette har langsomme klienter, så Apache ikke kan afslutte HTTP-forbindelsen og betjene en ny klient, så har vi den perfekte opskrift til at bruge en masse RAM på webserveren. Som alle systemadministratorer ved, så ender det rivegalt, for så begynder maskinen at page til swap-filen, og DET er langsomt.
Hvad kan vi gøre?
Målet er enkelt: vi skal bruge så lidt RAM som muligt i så kort tid som muligt, og helst på en måde så vi heller ikke bruger meget CPU-tid.
- Vi skal opdele så statiske filer kan serviceres af noget lettere end en Apache-process med en kæmpe PHP-vm på slæb.
- Vi skal forsøge at gøre køretiden under PHP så kort som mulig.
- Vi skal have CPU-forbruget ned. Det meste af CPU-tiden sker i PHP, så det skal der fokuseres på
Apache / mod_php – er der et alternativ?
Når man installerer “PHP”, så får man typisk en Apache-httpd med mod_php og mpm_prefork. Dette er fint og godt til sites med et minimum af trafik, og det virker på så godt som alle webapplikationer, man kan finde både i sit pakkearkiv og på nettet, men bruger altså kolossale mængder af RAM, hvis der kommer mange brugere på. For at få denne effekt, så må vi opdele i en frontend-server, der kan servicere statiske filer, og en backend, der kan servicere PHP. Vi har prøvet lidt forskelligt:
- Frontend: Apache / mod_fastcgi. Backend: php-cgi
- Frontend: NGINX. Backend: Apache / mod_php
- Frontend: Varnish. Backend: Apache / mod_php
Alle løsningerne kræver noget mere konfiguration, end et normalt Apache-setup. Der er nogle fordele og ulemper ved dem alle, og det er muligt at kombinere nogle af dem, for at opnå flere fordele.
Apache / mod_fastcgi
Denne løsning fokuserer på at skille PHP ud i et processrum for sig. Dette er ganske effektivt ud fra at reducere RAM-forbruget og iøvrigt bevare en vhost-konfiguration, man måtte have i Apache. Desværre har den vist sig lidt ustabil, blandt andet har vi set at Apache kan have svært ved at rotere logfiler korrekt. Løsningen er også sårbar overfor langsomme klienter. En php-cgi-process bliver således blokeret, så længe Apache og browser ikke er færdige.
NGINX
Vi har også prøvet løsninger, hvor en NGINX-webserver står foran Apache og proxier PHP-kald ind til Apache, mens den selv servicerer statiske filer. Denne løsning løser både vores primære problem med voldsomt RAM-forbrug og problemet med langsomme klienter, da det nu er NGINX, der taler med Apache og ikke klienten direkte. Desværre så skal NGINX også konfigureres, der skal sætte vhost-navn og aliaser, og du skal beslutte dig for hvilke filer NGINX skal aflevere direkte og hvilke den skal spørge Apache om. NGINX har også et konfigurationsformat, der er forskelligt fra Apache. Dette kan være en barriere, især hvis man har store mængder af manuelt vedligeholdt konfiguration.
Varnish
En anden løsning er at bruge Varnish http-accelerator. Varnish løser delvist problemet med konfigurationen, da den er meget simpel og med få linier kan kobles foran en hvilken som helst Apache-server og give en positiv effekt umiddelbart. Det løser problemet med langsomme klienter og er også med til at skærme Apache fra de fleste kald til statiske filer. Varnish læser ikke selv noget fra en DocumentRoot, men er kun en cache-proxy. Dette gør at effektiviteten varierer fra site til site. Til gengæld kan Varnish dog justeres og tunes meget effektivt, hvis man kender sin webapplikation, og er meget ressourceeffektivt og svarer ekstremt hurtigt ved cache-hit.
Hver af disse løsninger giver store forbedringer på især RAM-forbruget, men i visse tilfælde også en hastighedsforbedring. I visse tilfælde giver det mening at kombinere løsningerne i en trelags http-server-model
Varnish -> NGINX -> Apache/mod_php
I kommende blogindlæg vil vi se på hvordan disse opsætninger rent faktisk ser ud og hvordan man kan optimere dem i konkrete tilfælde.


