Denne sammenligning af PHP-handlere viser, hvordan mod_php, CGI, FastCGI, PHP-FPM og LSAPI Ydelse på din hosting – fra CPU-belastning til tail-latens. Jeg forklarer konkret, hvilket valg der er bedst for WordPress, WooCommerce og trafikspidser. Opladningstid sænker og samtidig skåner ressourcerne.
Centrale punkter
- PHP-FPM skaleres mere effektivt end mod_php og FastCGI.
- LSAPI leverer de bedste værdier på LiteSpeed.
- Isolering pr. bruger øger sikkerheden.
- OPcache og Redis reducerer ventetider.
- P95/P99 viser ægte brugeroplevelser.
Sådan fungerer PHP-handlere
En PHP-handler forbinder webserveren med fortolkeren og styrer Processer, hukommelse og I/O for hver anmodning. CGI starter en ny proces for hver anmodning og indlæser konfigurationer på ny, hvilket skaber overhead og Forsinkelse Forhøjet. Moderne varianter som FastCGI, PHP-FPM eller LSAPI holder arbejdere vedvarende klar og sparer dermed starttid, kontekstskift og CPU-cyklusser. OPcache forbliver i hukommelsen, hvilket betyder, at bytecode ikke skal kompileres hver gang, og dynamiske sider reagerer hurtigere. Samtidig bestemmer processtyringen, hvor mange samtidige anmodninger der må køre, hvordan prioriteterne fastsættes, og hvordan belastningstoppe kan afbødes.
Direkte sammenligning af de mest almindelige forhandlere
Valget af handler bestemmer Skalering, sikkerhedsmodellen og RAM-behovet for en applikation. mod_php integrerer PHP i Apache-processen og leverer korte svartider, men lider under svag Isolering mellem konti. CGI adskiller brugerne tydeligt, men koster massiv CPU-tid pr. anmodning. FastCGI reducerer overhead, men er stadig mindre effektivt end et godt tunet PHP-FPM. LSAPI går endnu et skridt videre, når LiteSpeed er i brug, og stabiliserer især tail-latens ved mange samtidige forbindelser.
| handler | Ydelse | Sikkerhed | Krav til RAM | Skalerbarhed | Operationelt scenarie |
|---|---|---|---|---|---|
| mod_php | Høj | Lav | Lav | Medium | Små steder, sjældne højdepunkter |
| CGI | Lav | Høj | Høj | Lav | Statisk indhold, test |
| FastCGI | Medium | Medium | Medium | Medium | midlertidig løsning |
| PHP-FPM | Meget høj | Høj | Lav | Høj | Delt hosting, CMS |
| LSAPI | Højeste | Medium | Meget lav | Meget høj | Høj trafik, e-handel |
PHP-FPM i praksis: Processer, puljer, tuning
PHP-FPM arbejder med worker-pools, der henter forespørgsler fra en kø og dermed Belastningsspidser elegant afbøde. Jeg opretter en separat pool for hver hjemmeside, så konfiguration, begrænsninger og brugerkontekst forbliver adskilt, og Sikkerhed stiger. I praksis betaler adaptive indstillinger som pm = dynamic eller ondemand sig, fordi antallet af aktive processer tilpasses efterspørgslen. Det er afgørende at dimensionere pm.max_children og tidsgrænserne korrekt, så køen ikke vokser, og der stadig er RAM-reserver. Til at begynde med anbefaler jeg at kontrollere parametrene struktureret; detaljer om finjustering forklarer jeg her: PHP-FPM processtyring.
LSAPI og LiteSpeed: Topværdi ved høj samtidighed
LSAPI holder PHP-processer i hukommelsen og reducerer kontekstskift, hvilket gør det muligt at levere dynamisk indhold med HTTP/3 og QUIC leveres endnu mere smidigt. Under fuld belastning forbliver P95/P99-latensen mere stabil end hos mange alternativer, hvilket gør Brugeroplevelse synligt forbedret. Jeg ser regelmæssigt flere forespørgsler pr. sekund og kortere TTFB på shop- og indholdssider, især når OPcache og servercache arbejder sammen. Fordelen viser sig ikke kun i gennemsnitsværdier, men også ved samtidige sessioner, sessioner med cache-misses og „kolde“ PHP-arbejdere. Hvis du vil forstå forskellen i arkitekturen, kan du læse oversigten over LiteSpeed vs. Nginx og træffer derefter en beslutning om stakken.
WordPress og WooCommerce: Korrekt klassificering af måleværdier
Med WordPress opnår jeg høje resultater med PHP 8.2 på FPM eller LSAPI. req/s-værdier, mens WooCommerce gennem sessioner, indkøbskurvlogik og flere databaseadgange klarer lidt færre anmodninger pr. sekund. Testen bliver først meningsfuld under realistiske Trafik blandet med caching-hits og -misses. Kritisk CSS, objektcache og persistente forbindelser flytter grænsen for, hvornår der opstår flaskehalse. Korte TTL'er for ofte ændret indhold og differentierede cache-nøgler for sprog, brugerstatus og enhedstype er særligt nyttige. På den måde forbliver siden hurtig, selvom den leverer personaliseret indhold.
Sikkerhed og isolation: Pools, brugerkontekst, begrænsninger
Jeg foretrækker separate servere til multi-user-hosting. Pools pr. konto, så rettigheder, stier og begrænsninger forbliver adskilt fra hinanden. mod_php deler en fælles kontekst, hvilket gør det Risiko øges, hvis et projekt har huller. FPM eller LSAPI med brugerkonfigurationer reducerer denne sårbarhed betydeligt, fordi processerne kører under den respektive bruger. Derudover er det muligt at indstille forskellige php.ini-indstillinger på projektniveau uden at påvirke andre websteder. Ressourcebegrænsninger som max_execution_time og memory_limit pr. pool forhindrer, at afvigelser bremser serveren.
Ressourceforbrug og RAM-planlægning
Hver PHP-worker bruger, afhængigt af kode, udvidelser og OPcache-Størrelsen varierer betydeligt, hvorfor jeg måler den faktiske belægning i stedet for at gætte. Værktøjer som ps, top eller systemd-cgtop viser, hvor meget RAM aktive arbejdere reelt belægger, og hvornår. Byttehandel truer. Derefter fastsætter jeg pm.max_children konservativt, lader headroom til database, webserver og cache-tjenester og observerer P95-latensen under peak. Hvis der er reserver tilbage, øger jeg antallet af børn gradvist og kontrollerer igen. På denne måde vokser den samlede kapacitet kontrolleret uden at overbelaste serveren.
Målemetode: Fra TTFB til P99
Jeg vurderer ikke kun gennemsnitsværdier, men frem for alt P95– og P99-latenser, fordi de afspejler den reelle oplevelse under belastning. En stack kan fungere med identisk gennemstrømning og alligevel virke dårligere ved P99, hvis Køer vokse. Derfor tester jeg kolde og varme caches, blander læse- og skriveforespørgsler og bruger realistiske samtidighedsværdier. Uden OPcache-opvarmning fortolker jeg resultaterne med forsigtighed, da mange systemer bliver betydeligt hurtigere efter få opvarmningskald. Først efter repræsentative testkørsler træffer jeg beslutning om håndtering, cachingstrategi og procesgrænser.
Beslutningsvejledning til valg af handler
For små sider med få logins er mod_php eller et sparsomt FPM-Opsætning, forudsat at sikkerhedsaspekterne er taget i betragtning. Hvis samtidigheden øges, skifter jeg til PHP-FPM med separate pools pr. projekt og aktiverer OPcache konsekvent. Ved meget dynamiske butikker og mange sessioner foretrækker jeg LiteSpeed med LSAPI for at holde P95 og P99 lave. Hvis man af pris- eller arkitekturmæssige årsager forbliver ved Apache/Nginx, fungerer en nøje afstemt FPM meget godt. I alle tilfælde tæller målinger under realistiske forhold mere end benchmarks på et tomt system.
Praksisopsætning: Caching, sessioner, tidsbegrænsninger
Jeg satser på OPcache med generøs Hukommelse-Allokering, så bytecode sjældent fortrænges, og flyt sessioner efter mulighed i Redis, for at undgå fil-låsninger. Dette reducerer ventetiden ved samtidige logins og personaliserede sider. For eksterne tjenester definerer jeg klare timeouts og circuit breakers, så nedbrud ikke blokerer hele anmodningen. På applikationsniveau holder jeg cache-TTL'er korte nok til at sikre aktualitet, men lange nok til at opnå en høj hit-ratio. Hvis du regelmæssigt støder på worker-begrænsninger, kan du finde en introduktion her: Balancér PHP-Worker korrekt.
Omkostnings-nytte-sammenligning og drift
Jeg vurderer Omkostninger en ændring mod den målbare gevinst i form af latenstid, gennemstrømning og pålidelighed. Overgangen fra FastCGI til PHP-FPM giver ofte mere end en ændring af PHP-underversionens nummer, fordi Proces-Management og caching virker kontinuerligt. LSAPI er især værdifuldt, hvis LiteSpeed alligevel er i brug, og der er mange samtidige besøgende. Hvis du ændrer stakken, bør du følge logfiler og målinger nøje og forberede rollback-stier. En planlagt A/B-drift over flere dage giver de mest pålidelige resultater.
Webserver-samspil: Apache-MPM, Nginx og Keep-Alive
I praksis er det ikke kun PHP-handleren, der er afgørende, men også webservermodus. mod_php fungerer med Apache i prefork-MPM, men blokerer brugen af moderne event-modeller. Hvis du vil betjene HTTP/2, længere keep-alive-faser og tusindvis af forbindelser effektivt, skal du satse på Apache. begivenhed + PHP-FPM eller på Nginx/LiteSpeed som frontend. Konsekvensen: Antallet af nødvendige PHP-arbejdere afhænger ikke af antallet af TCP-forbindelser, men af de faktiske på samme tid løbende PHP-anmodninger. HTTP/2/3-multiplexing reducerer således header-overhead på webserveren, men ændrer ikke noget ved for små PHP-puljer.
Nginx videresender typisk forespørgsler via FastCGI til FPM. Jeg sørger for, at read_timeout- og send_timeout-værdier på proxyen, ellers opstår der 502/504-fejl ved hængende upstreams, selvom PHP stadig fungerer. I Apache-miljøer begrænser jeg Keep-Alive, så lange inaktive forbindelser ikke binder thread-poolen. LiteSpeed abstraherer meget af dette, men udnytter først sin fordel fuldt ud med LSAPI.
OPcache, JIT og preloading: hvad der virkelig hjælper
OPcache er obligatorisk. I praksis dimensionerer jeg opcache.memory_consumption generøs (f.eks. 192–512 MB afhængigt af kodebasen) og øg opcache.max_accelererede_filer, så der ikke opstår evictions. For builds, der sjældent implementeres, deaktiverer jeg validere_tidsstempler eller sæt en højere revalidate_freq, for at spare syscalls. Forudindlæsning kan fremskynde rammer, men har især effekt ved en konsistent autoload-struktur. Det JIT fra PHP giver sjældent fordele ved klassiske web-workloads og kan endda koste RAM; jeg aktiverer det kun, hvis benchmarks under reelle forhold bekræfter dette.
Køhåndtering og modtryk
De fleste flaskehalse opstår ikke i CPU'en, men i kø. Hvis der kommer flere anmodninger ind, end medarbejderne kan behandle, vokser køen, og P95/P99-latensen skyder i vejret. Jeg sørger for, at pm.max_børn stor nok til at absorbere typiske spidsbelastninger, men lille nok til at bevare RAM-reserven. pm.max_anmodninger Jeg indstiller den moderat (f.eks. 500–2000), så hukommelseslækager ikke skaber langvarige processer. listen.backlog skal passe til webserverens backlog, ellers afbryder kernen forbindelser under belastning. Hvis man måler ankomstfrekvensen (anmodninger pr. sekund) og den gennemsnitlige servicetid, kan man ved hjælp af en simpel kapacitetsberegning vurdere, ved hvilken samtidighed latenstiden ændrer sig.
Timeouts, uploads og langdistanceløb
Lange uploads eller API-kald blokerer arbejdere. Jeg definerer klare grænser: max_udførelsestid og request_terminate_timeout i FPM forhindrer, at defekte anmodninger kører i evigheder. På proxy-niveau synkroniserer jeg proxy_read_timeout/fastcgi_read_timeout med FPM-grænserne, så der ikke opstår for tidlige 504-fejl. Store uploads streamer jeg og begrænser post_max_size og upload_max_filesize streng og planlæg dedikerede slutpunkter, så den resterende trafik ikke lider under det. For cron-lignende langdistanceløb flytter jeg arbejdet til Stikord eller CLI-opgaver i stedet for at blokere frontend-arbejdere i flere minutter.
Sessions og låsning i detaljer
PHP-sessioner er som standard spærrende. En anden anmodning fra samme bruger venter, indtil den første frigiver sessionen – hvilket er fatalt for WooCommerce, hvis der kører parallelle Ajax-kald. Jeg afslutter sessionens skriveadgang tidligt med session_write_close(), så snart der ikke længere er behov for mutationer. Med Redis som session-backend falder I/O-latensen, men låse-reglerne forbliver vigtige. Bag load balancere vælger jeg bevidst mellem sticky sessions (enkelt, mindre skalerbart) og stateless mønstre med objektcache, så horisontal skalering fungerer optimalt.
Overvågning og fejlfinding
Uden telemetri er tuning som at flyve i blinde. Jeg aktiverer FPM-status og slowlogs pr. pool for at se flaskehalse og identificere forespørgsler, der skiller sig ud.
; pr. pool pm.status_path = /status ping.path = /ping ping.response = pong request_slowlog_timeout = 3s slowlog = /var/log/php-fpm/www-slow.log pm.max_requests = 1000
Hvis der opstår 502/504-fejl, tjekker jeg først: Er FPM-køen fuld? Er der CPU-steal eller swap? Passer webserver-timeout med FPM-grænserne? Et kig i smaps pr. medarbejder viser den faktiske RSS-belægning, mens netstat/ss Afslører backlog-overskridelser. For OPcache overvåger jeg hitfrekvensen og antallet af revalideringer for at undgå evictions.
Containere, stik og ressourcebegrænsninger
I containere bruger jeg oftest TCP i stedet for Unix-sockets mellem webserver og FPM for at undgå navnerumsgrænser og lette belastningsbalancering. Det er vigtigt med konsistente cgroup-Begrænsninger: Hvis containeren kun har 1–2 GB RAM, skal pm.max_children være tilsvarende mindre, ellers træder OOM-killer i kraft. CPU-kvoter har stor indflydelse på reaktionstiden; jeg planlægger headroom og verificerer P95-latensen under grænsen. NUMA- og Core-Affinity-emner bliver relevante ved meget høj belastning, mens LSAPI i LiteSpeed-opsætninger optimerer meget af dette internt.
Multi-PHP-versioner og udvidelser
Mange værter kører flere PHP-versioner parallelt. Jeg isolerer puljer pr. version og holder Udvidelser slank. Hvert ekstra modul øger RAM pr. worker og kan forlænge opstartstiden. Jeg fjerner konsekvent ubrugte udvidelser; det giver ofte mere end en mindre pm.max_children-forøgelse. Ved opgraderingen planlægger jeg korte opvarmningsfaser for OPcache, så ikke alle brugere oplever koldstart på samme tid efter implementeringen.
RAM-diæt og realistisk kapacitetsplanlægning
I stedet for faste værdier beregner jeg det gennemsnitlige og øverste RAM-behov pr. worker med live-trafik. Herfra udleder jeg: (tilgængeligt RAM – system/DB/caches) / RAM pr. worker = maksimal fornuftig pm.max_children. Derudover holder jeg 15–25 % i reserve til burst, kernel-cache og uforudsete spikes. Hvis applikationen sporadisk oppuster hukommelsen, sænker jeg grænsen eller reducerer pm.max_requests for at genbruge processer oftere.
Teststrategi: Reproducerbar belastning og realistiske mønstre
Jeg bruger testprofiler, der blander kolde og varme caches, kombinerer GET/POST og øger samtidigheden gradvist. Vigtigt: Først med aktiv OPcache og realistiske tænketider kan jeg se, om systemet forbliver stabilt under brugsadfærd. En ramp-up over flere minutter forhindrer kunstige spidsbelastninger ved opstart. Evalueringen fokuserer på TTFB og P95/P99, ikke kun på gennemsnitlig RTT eller ren req/s.
Fejlbilleder fra praksis
- Mange 504 under Peak: FPM-kø fuld, backlog for lille, timeouts på proxyen tættere end i FPM.
- Stamming ved deployeringer: OPcache-fortrængninger, manglende opvarmning, for lille opcache.memory_consumption.
- Gode gennemsnitsværdier, dårlige P99: For mange langdistanceløb (I/O, eksterne API'er), manglende circuit breaking.
- Høj CPU, lav req/s: Session-låse eller ikke-cachelagrede databaseforespørgsler, der begrænser serielt.
Driftsikkerhed og rollback
Enhver ændring af handleren eller poolparametrene kører jeg med Funktionelle flag eller gradvist. Jeg holder øje med fejl- og slowlogs, P95 og fejlprocent og definerer en klar nedlukning, hvis målingerne tipper. En anden pool med identisk version, men andre parametre, muliggør hurtig A/B-skift uden nedetid. Under fuld belastning viser en kort, automatisk reduktion af samtidighed (backpressure) sig at være effektiv i stedet for at starte nye arbejdere ukontrolleret.
Kort opsummeret
Til dynamiske websteder med mange samtidige brugere foretrækker jeg LSAPI på LiteSpeed, mens PHP-FPM på Apache eller Nginx giver det bedste Allrounder mod_php forbliver et særligt tilfælde for meget enkle projekter uden streng isolation. Det afgørende er realistiske tests med varm OPcache, fornuftige poolgrænser og ren caching. Hvis man pålideligt reducerer latenstider, måler man P95/P99 og reagerer først på tail-problemer i stedet for gennemsnitsværdier. På den måde opnår en applikation mærkbart hurtigere svar og flere reserver til spidsbelastning.


