Hvorfor vi skiftede fra Apache til LiteSpeed


Posted on Aug 11, 2018 | By Hosting4Real

Tidligere på året begyndte vi at skifte fra Apache til LiteSpeed webserver på vores infrastruktur. Denne ændring foregik over flere måneder, med de første tests sidste år i November.

I slutning af April og begyndelsen af Maj, valgte vi at skifte til den nye webserver på tværs af vores infrastruktur efter omfattende tests og meget få kompatibilitetsproblemer.

Dette indlæg handler om hvorfor vi lavede skiftet, hvad problemer vi så under skiftet og hvad problemer det løste ved faktisk at skifte til LiteSpeed.

Hvorfor vi ønskede at skifte

En af de hovedsaglige grunde til vi ønskede at skifte fra Apache til LiteSpeed var grundet et igangværende problem med Apache når vi brugte mpm_event og lsphp i et CloudLinux miljø.

Problemet vi oplevede var at når vi ville genstarte webserveren, ville det ret ofte resultere i at alle forbindelser til webserveren ville blive blokeret i en periode af 5 til 15 sekunder. Dette er ufattelig lang tid når det sker mellem 10 og 50 gange om dagen - problemet kunne løses ved at skifte til en webserver der kan lave "graceful restarts" korrekt.

Et andet problem vi oplevede med Apache, var hvis man havde en større mængde mod_security regler i vores "Web Application Firewall", ville der være tider hvor CPU forbruget i webserveren var utrolig højt. Hvis der blev lavet større POST-forespørgsler, kunne vi se at processerne ville gå til 100% på en enkelt CPU kerne, udelukkende for at behandle disse regler.

Problemet var mere tydeligt på nogle servere i forhold til andre, og det skyldes hovedsageligt det mønster af trafik der blev lavet, samt typen af sider de enkelte servere havde.

Nummer 3 problem vi så var skaleringsproblemer med hjemmesider der laver en stor mængde trafik.

Hos Hosting4Real hoster vi relativt store hjemmesider, hvis man kigger på deres trafikmønster, enten i form af mange forespørgsler i en meget kort periode, eller hvor at forbindelser mod besøgende ville blive holdt åben i lang tid. Apache er ikke ret glad for forespørgsler der skal holde forbindelsen åben i længere tid.

Måden Apache behandler forespørgsler på, er at tildele en ny "worker" (tråd) for at håndtere levetiden af den given forbindelse til en besøgende - dette virker fint i små miljøer, eller hvor forbindelserne er relativt korte rent tidsmæssigt.

Med LiteSpeed webserver, som er "event-driven", betyder det at den kan håndtere tusindevis af samtidige forbindelser, hvilket er en af de grunde til vi valgte LiteSpeed fremfor en anden webserver løsning.

Hvorfor vi valgte LiteSpeed

Der er en række alternativer til Apache, nogle af dem er gratis og andre koster penge.

Vi valgte at tage LiteSpeed i brug fordi det er en såkaldt "drop-in" løsning til Apache, så det understøtter mange af de ting som Apache gør (så som .htaccess) og samtidig fordi at det er officielt understøttet af cPanel som vi bruger til kontrolpanel.

LiteSpeed kommer også med funktioner så som QUIC, TLSv1.3, HTTP/2 Push, Brotli komprimser, ESI caching og har caching plugins til systemer så som WordPress, Joomla, Prestashop, Thirtybees, Magento, Xenforo, Drupal og MediaWiki.

Funktioner så som QUIC og Brotli giver os muligheden for at levere hjemmesider endnu hurtigere til besøgende, og dette alene bringer en hel del værdi for vores kunder.

Den hovedsaglige grund til at skifte til LiteSpeed var dog for at løse 2 problemr:

WAF bruger meget CPU

Selvom vi bruger det samme "ruleset" i vores mod_security konfiguration, ser vi et betydeligt lavere forbrug i ressourcer. Dette kommer sig af måden som LiteSpeed har implementeret mod_security på. Dette resultere i at vi nedsætter forbruget af ressourcer brugt på vores servere, og derved har flere tilgængelige til vores kunder.

Blackouts under genstart

Apache havde problemet at det ville droppe forbindelser når vi genstartede webserveren. Dette sker fordi Apache i virkeligheden ikke kan lave en graceful restart. LiteSpeed løser dette ved at starte en ny process, og først når denne process er startet, vil den gamle process lukke ned.

Problemer vi oplevede under/after skiftet

LiteSpeed er en "drop-in" løsning til Apache, men der er nogle specifikke funktioner som ikke er implementeret af flere grunde.

Generelt hvis vi kigger på mængden af sider vi hoster, så var der kun meget meget få sider der faktisk havde problemer med skiftet. Disse problemer kommer fra fejl i selve softwaren som de enkelte hjemmeside bruger, men disse fejl ville ikke være synlige under Apache fordi at Apache har nogle grundlæggende designproblemer. Hvilket resulterede i at det er fejl der er svære at fange inden skiftet.

Fejl når man bruger [OR] i mod_rewrite regler

Når du bruger mod_rewrite regler på din hjemmeside, vil man oftest skulle validere specifikke betingelser. En af disse betingelser kunne være at man skulle komme fra Denmark og at IP'en ikke matxher 8.8.8.8, i det tilfælde ville man skulle bruge kode så som følgende:

RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(DK)$
RewriteCond %{REMOTE_ADDR} !=8.8.8.8
RewriteRule ^(.*)$ /en/ [L,R=302]

Hvis man derimod vil sige at hvis personen kommer fra Denmark eller IP'en ikke er 8.8.8.8, vil man skulle ændre sin RewriteCond til noget lign:

RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(DK)$ [OR]
RewriteCond %{REMOTE_ADDR} !=8.8.8.8
RewriteRule ^(.*)$ /da/ [L,R=302]

Hvis én af de overstående betingelser er mødt, vil man få en 302 viderstilling til /da/.

Dette virker fint i både Apache og LiteSpeed - men f.eks. i Prestashop hvis man havde en enkelt side med "media servere" slået til, ville dette resultere i en fejl som kun var synlig når man bruger LiteSpeed.

Koden som Prestashop laver er noget lign dette:

RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$1$2$3$4.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$1$2$3$4$5.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$1$2$3$4$5$6.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$1$2$3$4$5$6$7.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$6/$1$2$3$4$5$6$7$8.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$6/$7/$1$2$3$4$5$6$7$8$9.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$6/$7/$8/$1$2$3$4$5$6$7$8$9$10.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^c/([0-9]+)(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2$3.jpg [L]
RewriteCond %{HTTP_HOST} ^cdn-static.mediaservers.prestashop-domain.com$ [OR]
RewriteRule ^c/([a-zA-Z_-]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2.jpg [L]

Hvad der sker i overstående eksempel er du har en RewriteCond der ville lave matche domænet for media serveren, men der ville være en [OR] i slutningen.

Apache ignorerer dette og vil køre reglerne som om at denne RewriteCond ikke eksisterede. Hvor hvis man bruger LiteSpeed, vil den læse reglerne som der er angivet, så reglerne ville aldrig blive matche hvis man efterspurgte et billed dirkete via shoppens URL, fordi reglerne kun ville gælde for domænet cdn-static.mediaservers.prestashop-domain.com grundet den RewriteCond.

En simpel løsning på dette ville være ikke at tilføje RewriteCond overhovedet; Men da Prestashop bruger det når du bruger en multistore-opsætning, kan man blot tilføje butikkens eget domæne til din RewriteCond, som f.eks bliver gjort hvis du har multistore aktiveret.

Vi lavede et pull request til Prestashop core samt Thirtybees for at forklarer problemet og det er blevet udgivet.

Vi valgte at lave en patch til Prestashop's kode, da det faktisk også er ugyldigt når du bruger Apache - Apache ignorerer dog blot denne fejl og forsætter. Den bedste løsning var at løse problemet i softwaren der skabte problemet, hvilket i dette tilfælde er Prestashop.

Fortolkning af [L] flag

I mod_rewrite har du et [L] flag som i Apache skal stoppe behandling af dine mod_rewrite regler, men funktionaliteten er forskellig (ubevist) baseret på hvad kontekst du arbejder i. Hvis du har dine mod_rewrite regler i din Apache "vhost" kofniguration, vil reglerne fungere anderledes end hvis du havde dem i .htaccess. At disse bliver håndteret forskelligt er en fejl i Apache, og det er et kendt problem med der er ingen løsning for det endnu (måske kommer det en dag?).

I specifikationen om hvordan disse mod_rewrite flag skal virke, er det angivet at [L] skal stoppe behandlingen af regler, LiteSpeed følger denne specifikation til punkt og prikke - hvor Apache ikke har fulgt deres egen specifikation helt korrekt og derved har introduceret denne fejl.

Man kunne argumere for at dette er en fejl i webserveren ved at behandle reglerne forskelligt på trods af at det er en "drop-in" løsning. Specifikationen bliver dog fulgt som den skal så det faktiske problem ligger i at Apache ikke overholder deres egen specifikation, men endnu vigtigere at software så som Prestashop er afhængig af en funktionalitet der er implementeret forkert i webserveren.

Vi prøver at finde en patch til Prestashop som kan blive en del af deres nye versioner. Vi har samtidig spurgt LiteSpeed om de kan tilføje en funktionalitet til at "bryde" specifikationen og virke på samme måde som Apache gør, hvis folk er dybt afhængige af denne funktionalitet.

Konklusion

Generelt gik skiftet godt, det har reduceret servernes samlet ressourceforbrug og forbedret hastigheden for alle vores kunder.

Det giver os muligheden for at tilbyde bedre caching muligheder til vores kunder samt tilbyde funktionaliter så som HTTP/2 Push, QUIC og TLSv1.3.

Kigger vi på stabiliteten, er den blevet betydeligt bedre, da vi ikke har disse blackouts mere, og vi har ikke problemet hvor at lsphp til tider ville resulterede i at hovedprocessen ville "crashe".

Det har også givet os muligheden for at bidrage til open source projekter så som Prestashop, Thirtybees og WordPress.

Det resulterede i nogle få fejl under skiftet. Selvom vi ikke bryder os om at det kan have påvirket få sider, så bringer det en forbedring til alle andre sider. Vi skal se på det større billede i dette tilfælde.

Posted in: General