Är din webbplats en riktig HIT? Se till att cachningen fungerar

Photo by Guillaume Bolduc on Unsplash

Förväntar du dig att din webbplats kommer att få många besökare? Det är inget att oroa sig för om Seravo är ditt webbhotell. Men om du ändå vill vara extremt väl förberedd och säkerställa att din WordPress-webbplats laddas så fort som möjligt bör du kontrollera att HTTP-cachningen fungerar korrekt för din webbplats.

Cache-hanteringen som sker på HTTP-nivån sparar en kopia av hela det HTML-dokument som din WordPress-kod skapar i PHP-miljön. Om denna kopia kan användas i stället för att HTML-dokumentet behöver skapas på nytt i PHP kan dokumentet laddas på bara några millisekunder. Cachehantering på HTTP-nivån bygger på gemensamma standarder för hela webben och några speciella HTTP-headers för kontroll av cache så denna del är inte på något sätt unik för Seravo. Dessutom kommer besökarnas webbläsare och eventuella mellanliggande proxyservrar i nätverket att lagra HTML-dokumentet för att hjälpa dina besökare att ladda sidor snabbare.

Låt oss ta en titt på hur dessa HTTP-headers ser ut. Nedan följer ett exempel på de HTTP-headers som skickas från webbplatsen för den Svenska WordPress-gemenskapen. Vi hämtade startsidan wpsv.se med hjälp av kommandoradsverktyget cURL som tagits fram av öppen källkodsutvecklaren Daniel Stenberg som faktiskt råkar vara svensk. Administratörerna hos Seravo använder cURL varje dag för att testa kundernas webbplatser.

$ curl -IL https://wpsv.se/
HTTP/1.1 200 OK
Date: Wed, 25 Apr 2018 17:47:59 GMT
Content-Type: text/html; charset=UTF-8
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Link: <https://wpsv.se/wp-json/>; rel="https://api.w.org/"
Link: <https://wpsv.se/>; rel=shortlink
X-Proxy-Cache: MISS P: A: N:

Det är många HTTP-headers som skickas ut. Vi har kortat ned exemplet något genom att utesluta några rader. På den första raden ser vi att sidan gav resultatkoden ”200 OK”, vilket betyder att allt gick bra. Alla fälten Date, Content-Type, Expires, Cache-Control och Link är standard-headers i HTTP. Fältet X-Proxy-Cache är ett specialfält som bara Seravos servrar skickar ut.

Fälten ”Expires” och ”Cache-Control” informerar webbläsaren (och alla mellanliggande HTTP-proxyer) hur lång livslängd innehållet har och i vilken mån det kan sparas i cache-minne. I detta exempel berättar de att innehållets giltighetstid slutade redan tidigare och att cache-lagring inte är tillåten. HTML-dokument som skickas med dessa HTTP-headers kommer aldrig att cache-lagras någonstans över huvud taget.

Hos Seravo skickas HTTP-headers antingen från PHP-koden i WordPress (med hjälp av PHP-fuktionen header()) eller kundens egen Nginx-konfiguration i /data/wordpress/nginx/.

Det visar sig att denna webbplats har satt konstanten define('WP_DEBUG', true); i filen wp-config.php och när felsökningsläget är aktiverat skickar WordPress dessutom headers som förbjuder cache-lagring. I detta fall lyckades vi bli av med header-fälten som förhindrade cache-lagring genom att ta bort den raden i wp-config. Så här såg header-fälten ut efter den korrigeringen.

$ curl -IL https://wpsv.se/
HTTP/1.1 200 OK
Date: Wed, 25 Apr 2018 18:14:41 GMT
Content-Type: text/html; charset=UTF-8
Link: <https://wpsv.se/wp-json/>; rel="https://api.w.org/"
Link: <https://wpsv.se/>; rel=shortlink
X-Proxy-Cache: HIT P: A: N:

Observera även värdet för header-fältet X-Proxy-Cache. Nu står det att sidan är en träff – ”HIT”. Det betyder att svaret levererades från HTTP-proxyn och inte från den bakomliggande PHP-miljön. För en utvecklare är målet att besökarna får statusen HIT så ofta som möjligt.

Servern är inte den enda parten som skickar HTTP-headers. Även klienten (webbläsaren) skickar header-fält. Faktum är att om någon cookie finns definierad i webbläsaren kommer header-fälten i förfrågan att innehålla en rad som inleds med nyckelordet Cookie, följt av ett kolon och ett värde. Om HTTP-förfrågan från klienten har en cookie definierad kommer svaret från webbservern troligen inte från cache-minnet eftersom cookien är ett tecken på att besökaren är en inloggad användare och att WordPress kommer då att vilja skapa unikt innehåll för varje enskild besökare, t.ex. leverera en sida som visar texten ”Hej, Otto” i det övre högra hörnet för just denna besökare och inte visar samma sida för alla andra besökare. Det innebär att cookies kommer att bryta cache-lagringen.

Ett annat möjligt header-fält i HTTP-förfrågan är Pragma: no-cache. Om du i Chrome eller Firefox trycker på Ctrl-F5 för att tvinga en komplett omladdning av en sida skickas faktiskt just detta header-fält från klienten till servern. Samma instruktion kan skickas från kommandoraden med programmet curl enligt följande:

$ curl -IL -H Pragma:no-cache https://wpsv.se/
HTTP/1.1 200 OK
Date: Wed, 25 Apr 2018 18:14:54 GMT
Content-Type: text/html; charset=UTF-8
Link: <https://wpsv.se/wp-json/>; rel="https://api.w.org/"
Link: <https://wpsv.se/>; rel=shortlink
X-Proxy-Cache: BYPASS P:no-cache A: N:

Observera att vi här ser ytterligare ett möjligt värde i X-Proxy-Cache. De olika möjliga värdena som kan erhållas är HIT, EXPIRED, BYPASS och STALE. Om du får statusen MISS betyder det att sidan överhuvudtaget inte cache-lagras på HTTP-nivå. De andra statusorden informerar dig om cache-statusen för förfrågan. Som utvecklare ser du helst att man för det allra mesta får svaret HIT och bara någon gång ibland något annat.

Curl innehåller en enorm mängd funktioner och är en fantastisk verktygslåda för webbutvecklare när de behöver felsöka vad som sker på HTTP-nivån i samspelet mellan webbläsaren och webbservern. En möjlighet som hör till våra favoriter är att skriva ut den totala tid det tog för svaret att anlända.

$ curl -I -s -w "%{time_total}\n" https://wpsv.se/
HTTP/1.1 200 OK
Date: Wed, 25 Apr 2018 18:20:39 GMT
Content-Type: text/html; charset=UTF-8
Link: <https://wpsv.se/wp-json/>; rel="https://api.w.org/"
Link: <https://wpsv.se/>; rel=shortlink
X-Proxy-Cache: HIT P: A: N:
0,080179

$ curl -I -s -w "%{time_total}\n" -H Pragma:no-cache https://wpsv.se/
HTTP/1.1 200 OK
Date: Wed, 25 Apr 2018 18:20:53 GMT
Content-Type: text/html; charset=UTF-8
Link: <https://wpsv.se/wp-json/>; rel="https://api.w.org/"
Link: <https://wpsv.se/>; rel=shortlink
X-Proxy-Cache: HIT P: A: N:
1,072267

Detta visar att förfrågan fullföljdes på 80 millisekunder när svaret hämtades från proxy-funktionens cache-lagring men när svaret hämtades ända från PHP-miljön tog det en sekund. En sekund är faktiskt ganska lång tid, och nästa vecka kommer vi att blogga om sådana verktyg som XDebug som kan användas för att analysera varför det tar så lång tid i PHP-miljön att det går åt en hel sekund för att generera sidans HTML-kod.

Observera att om dessa tester körs från din bärbara dator kommer den uppmätta tiden att inkludera nätverksfördröjningen i ditt lokala trådlösa nätverk och för alla övriga hopp mellan din dator och servern. För att alltid kunna uppmäta jämförbara resultat är det därför en rekommendation att man kör curl direkt på webbservern ifråga i en terminalförbindelse via SSH.

Eftersom detta är en vanligt förekommande åtgärd har vi skapat två bekväma kommandon för våra kunder som låter dem testa hur lång tid det tar för WordPress att leverera sidor: wp-speed-test och wp-load-test. Se nedanstående exempel.

wpsv@wpsv_1e5ea3:/data/wordpress/htdocs$ wp-speed-test
Testing speed URL https://wpsv.se...

For an explanation of the different times, please see docs at https://curl.haxx.se/docs/manpage.html

URL TOTAL NAMELOOKUP CONNECT APPCONNECT PRETRANSFER STARTTRANSFER = AVG
https://wpsv.se 1.174 0.125 0.126 0.132 0.132 1.174 1.174
https://wpsv.se 0.478 0.000 0.000 0.000 0.000 0.478 0.826
https://wpsv.se 1.017 0.000 0.000 0.000 0.000 1.017 0.890
...
https://wpsv.se 0.579 0.000 0.000 0.000 0.000 0.579 0.864
https://wpsv.se 1.163 0.000 0.000 0.000 0.000 1.163 0.880
https://wpsv.se 0.594 0.000 0.000 0.000 0.000 0.594 0.865

Test completed. If the values seems too high, please profile your PHP code to find potential bottle necks.
Note that this test tells how fast your site is in the sense of how long it takes for PHP to generate the 
HTML output. To test how much load the site can handle, run wp-load-test.

wpsv@wpsv_1e5ea3:/data/wordpress/htdocs$ wp-load-test
Testing capacity of URL https://wpsv.se...

URL COUNT ELAPSED TIME RESPONSE TIME
https://wpsv.se 1 1 1.130
https://wpsv.se 2 2 1.040
https://wpsv.se 3 3 0.995
...
https://wpsv.se 38 29 0.571
https://wpsv.se 39 29 0.568
https://wpsv.se 40 30 0.567

Test ended after 30 seconds and 40 requests with an average of 1.3 requests per second.
This test only uses a single PHP worker and it bypasses the edge cache. The actual site 
will be capable of handling much more traffic. If the response time of a single PHP 
request is much above 0.500 seconds, please try to optimize the PHP code and run wp-speed-test. 
If the response time is much below 0.100 seconds, then this test is likely to trigger the 
flood protection and server will yield 429 responses.

Du kan dessutom lägga till parametern –cache för att se hur snabbt sidan laddas om den hämtas av utomstående besökare där HTTP-proxyn används:

wpsv@wpsv_1e5ea3:~$ wp-speed-test --cache
Testing speed URL https://wpsv.se...

Warning: invoked with --cache and thus measuring cached results. This does not measure actual PHP speed.

For an explanation of the different times, please see docs at https://curl.haxx.se/docs/manpage.html

URL TOTAL NAMELOOKUP CONNECT APPCONNECT PRETRANSFER STARTTRANSFER = AVG
https://wpsv.se 0.041 0.028 0.030 0.036 0.036 0.041 0.041
https://wpsv.se 0.006 0.000 0.000 0.000 0.000 0.005 0.014
https://wpsv.se 0.005 0.000 0.000 0.000 0.000 0.005 0.008
https://wpsv.se 0.005 0.000 0.000 0.000 0.000 0.005 0.007
https://wpsv.se 0.006 0.000 0.000 0.000 0.000 0.006 0.007
https://wpsv.se 0.005 0.000 0.000 0.000 0.000 0.005 0.007

Båda dessa kommandon godtar även en specifik URL som parameter, vilket låter dig testa en viss sida på din webbplats:

wpsv@wpsv_1e5ea3:~$ wp-speed-test https://wpsv.se/?wpsvorg_feed=1
Testing speed URL https://wpsv.se/?wpsvorg_feed=1...

For an explanation of the different times, please see docs at https://curl.haxx.se/docs/manpage.html

URL TOTAL NAMELOOKUP CONNECT APPCONNECT PRETRANSFER STARTTRANSFER = AVG
https://wpsv.se/?wpsvorg_feed=1 0.088 0.028 0.029 0.035 0.036 0.088 0.088
https://wpsv.se/?wpsvorg_feed=1 0.038 0.000 0.000 0.000 0.000 0.037 0.063
https://wpsv.se/?wpsvorg_feed=1 0.037 0.000 0.000 0.000 0.000 0.037 0.054
https://wpsv.se/?wpsvorg_feed=1 0.037 0.000 0.000 0.000 0.000 0.037 0.040
https://wpsv.se/?wpsvorg_feed=1 0.037 0.000 0.000 0.000 0.000 0.037 0.040
https://wpsv.se/?wpsvorg_feed=1 0.037 0.000 0.000 0.000 0.000 0.037 0.040

Nu är det dags för dig att testa din egen webbplats och se till att den skickar alla HTTP-headers den borde. Lycka till med optimering!