Om de laadtijd van een website tot een minimum te reduceren, is het handig om een HTTP-cache te gebruiken. Met Varnish kun je de responstijd terugbrengen tot enkele milliseconden.
Hoewel de statische webpagina aan een kleine revival bezig is, zijn de meeste moderne websites enorm complexe bouwwerken. De dynamisch content is afkomstig van verschillende bronnen en servers en wordt voordat hij aan de bezoeker wordt geserveerd eerst tot een geheel gesmeed. Om het overzicht niet te verliezen en het beheer te versimpelen, wordt die taak meestal vervult door een contentmanagementsysteem. Deze voegt een webpagina samen uit talloze kleine elementen. Zonder caching of andere maatregelen betekent dit dat de pagina bij elke request opnieuw berekend moet worden. Dit kost elke keer relatief veel rekenkracht en belast daarmee de server onnodig. Om dit te voorkomen kun je Varnish de respons van de webserver te bufferen en hem zo te ontlasten.
Als de gevraagde pagina in de cache zit, krijgt de browser die versie toegestuurd en hoeft hij dus niet opnieuw berekend te worden. Vooral bij complexe webapplicaties kun je daarmee de responstijd van een server flink verlagen. Waar je eerst nog één tot twee seconden moest wachten op een antwoord, krijg je de gevraagde informatie met Varnish al binnen een paar milliseconden terug. Dat versnelt het opbouwen van de pagina bij de bezoekers en wordt daarom door Google beloond met een hogere ranking in de zoekresultaten.
Varnish is de versneller voor het laatste stuk. De software heeft geen problemen met druk bezochte websites en kan behalve als cache ook als load balancer werken om requests over meerdere dedicated servers te verdelen.
Praktijksituatie
Ook onze eigen webshop gebruikt Varnish om het uitleveren van pagina’s te versnellen. Al zit de software hier verpakt in MageBoost, een speciale cloudserver die is ontwikkeld door onze hostingprovider HostingXS om Magento-shops te versnellen. MageBoost bestaat uit diverse lagen, waaronder Varnish en de in-memory database Redis. Op iedere laag waarop Magento rekenwerk moet verrichten, wordt een getunede versie van Varnish toegepast. De webservercache levert in twee richtingen voordeel op: bezoekers krijgen de pagina’s vele malen sneller binnen en bij de hoster worden de servers minder belast, zodat ze efficiënter kunnen werken.
De meest recente versie van Varnish is versie 5.0. Helaas bieden veel distributies nog versie 4.0 of 4.1 aan. Oudere versies dan 4.0 gebruiken een andere syntaxis dan ons configuratiebestand, waardoor onze voorbeeldconfiguratie niet zonder aanpassing werkt. De Varnish-ontwikkelaars bieden een eigen repository aan waarin je de nieuwste versie voor Ubuntu, Debian, Red Hat Enterprise Linux, CentOS en FreeBSD kunt vinden. Op de website van het project staat beschreven hoe je dit doet.
Alleen HTTP
Varnish kan alleen overweg met HTTP-verbindingen, dus niet met HTTPS. Als je je website (ook) via HTTPS wilt aanbieden, moet een SSL-reverse-proxy of een webserver als Nginx of Apache zorgen voor het versleutelen van de verbinding tussen je server en de client.
Als je al een webserver op je computer hebt staan die op poort 80 werkt, moet je die bijvoorbeeld omleiden naar poort 8080. Die poort moet je dan alleen nog via het lokale loopback-adres 127.0.0.1 openen. Varnish neemt dan poort 80 in gebruik voor requests van buitenaf. Varnish kan ook op een eigen computer draaien en een of meerdere webservers versnellen. Als je altijd actuele individuele content moet leveren, moet je je afvragen op welke plekken caching van nut is. Anders kan het gebeuren dat de gegevens die bezoekers te zien krijgen verouderd zijn.
Varnish voegt niet veel toe als je server sowieso voornamelijk afzonderlijke HTML-bestanden levert. Als je performanceproblemen hebt met je website, moet je eerst eens naar de database, de webserver en eventueel je CMS kijken of daar niet de bottleneck zit. Voor een kleine blog met een paar honderd bezoekers per maand heeft het installeren van Varnish amper nut.
Installeren
Het installeren van Varnish op Debian Jessie (en Ubuntu) doe je heel eenvoudig met apt install varnish. Om ervoor te zorgen dat het programma met de HTTP-poort werkt, moet je de bijbehorende service-unit bewerken. Het Debian-pakket installeert wel het bestand /etc/default/varnish, maar dat wordt bij Debian met sysvinit ingelezen. In combinatie met systemd is het nutteloos. Maak een kopie van de service-unit van Varnish om ervoor te zorgen dat het bestand bij een update niet overschreven wordt. Kopieer daarom /lib/systemd/system/varnish.service naar /etc/systemd/system/varnish.service.
Daarna bewerk je het gekopieerde bestand. Varnish gebruikt standaard poort 6081 voor HTTP-requests en poort 6082 voor administratieve doeleinden. Op de regel die met ExecStart= begint verander je de parameter -a :6081 in -a :80. Varnish antwoordt dan meteen op HTTP-requests. Met de parameter -s malloc,256m stel je in dat Varnish 256 MB werkgeheugen als werkcache reserveert. Afhankelijk van de hoeveelheid aanwezige RAM kun je dat uitbreiden. Als je een aparte computer voor Varnish gebruikt, kun je er flink wat geheugen aan toekennen. De ontwikkelaars adviseren ongeveer 75 procent van het totale werkgeheugen. Als Varnish het werkgeheugen met andere services moet delen, moet je wat conservatiever zijn in het toekennen. Als het dringen wordt in het geheugen, kun je met –s file,1G, /var/lib/varnish/varnish_storage.bin een cache van 1 GB op de harde schijf aanmaken. Na een herstart met service varnish restart gebruikt Varnish de wijzigingen.
Configureren
Het configuratiebestand /etc/varnish/default. vcl bepaalt hoe de cache met de HTTP-requests moet omgaan. Het bestand is geschreven in de Perl-achtige Varnish Configuration Language VCL. De sectie backend stelt de hostnaam en een poort in voor de back-end, oftewel de bron-webserver. Die bron kan ook een externe webserver zijn. Door meerdere back-ends op te geven kun je bijvoorbeeld een load-balancing-systeem maken. Maar daarvoor moet Varnish nog wel extra geconfigureerd worden.
Het voorbeeldbestand heeft nog vier delen: vcl_recv, vcl_backend_response en vcl_deliver en een Access Control List onder het sleutelwoord acl. Bij de sectie vcl_recv komt de request van de client (req) binnen. Die bevat alle aanwijzingen die Varnish afwerkt voor het aanroepen van de cache. Die verwijderen bijvoorbeeld nutteloze cookies of voegen redirects in.
vcl_backend_response verwerkt het antwoord van de back-end (resp) en verwijdert bijvoorbeeld overbodige headers. Bovendien wordt daar de geldigheidsduur (TTL) van de objecten in de cache bepaald. De commando’s in vcl_deliver verwerken de uitvoer van Varnish voordat die naar de client verstuurd wordt. Regels die hier staan voegen bijvoorbeeld extra headers in en melden daarmee naar buiten toe of een antwoord uit de cache van Varnish kwam of nieuw gemaakt is.
Voorbeeldconfiguratie Varnish
Het configuratievoorbeeld werkt met een back-end op 127.0.0.1:8080. Als een request van een client binnenkomt, wordt die binnen vcl_recv verwerkt. Eerst stelt het If-blok in regel 13 de HTTP-header XForwarded-For in of breidt die uit met het ip-adres van de client, maar alleen als Varnish de request niet al een keer verwerkt heeft. De header meldt aan alle volgende proxy’s en webservers welke ip-adressen de voorgaande stations van de request hebben. In regel 21 regelt de If-voorwaarde de afhandeling van Purge- en Domainpurgerequests. Die dienen ervoor de cache indien nodig te legen. Om te voorkomen dat iedere client de cache kan legen en Purgeen Domainpurge-request kan verzenden, beperkt de ACL Purge (regel 8) de toegang tot het loopback-adres. In regel 22 vergelijkt de If-voorwaarde het ip-adres van de client (client.ip) met de ACL. Requests van externe ip-adressen worden door Varnish verworpen en beantwoord met de HTTP-code 405 (Method not allowed).
Varnish cachet geen webpagina’s die een cookie bevatten. Dat betreft zowel requests van clients als antwoorden van back-ends. Varnish cachet daarom ook geen pagina’s die tracking-cookies gebruiken. De If-voorwaarde in regel 28 van vcl_ref verwijdert met behulp van een reguliere expressie cookies die met een underscore beginnen of de string has_js bevatten. Dergelijke cookies worden bijvoorbeeld door Google Analytics gebruikt, maar zijn voor webservers niet van belang en kunnen daarom verwijderd worden. Tot slot (regel 32) zorgt de configuratie er aan de hand van de opgevraagde url nog voor dat Varnish geen statische en grote bestanden als mp3’s en pdf’s cachet, maar die altijd rechtstreeks van de webserver haalt.
Cacheduur
De sectie vcl_backend_response stelt de geldigheidsduur van het gecachete object in met het sleutelwoord beresp.ttl. Daarbij staat beresp voor ‘backend response’. In het voorbeeld vervalt een gecachete object na vijf minuten, tenzij het een CSS- of JavaScript-bestand is. Die worden een dag lang gecachet. Als die bestanden wijzigen, moet je hun bestandsnaam veranderen, anders krijgen bezoekers maximaal een dag de gecachete en verouderde versie geleverd. Je kunt hier ook dagen instellen in de vorm van 3d, uren als 2h en seconden als 10s. vcl_deliver voegt nog de header X-Cache toe (regel 46). Als Varnish een request uit de cache beantwoordt, wordt die op HIT gezet, anders op MISS.
Gereedschapskist
Varnish heeft een kleine verzameling tools, met onder meer Varnishlog, dat de metadata en headers van de lopende requests laat zien. Je moet de uitvoer daarvan bij een goed bezochte server wel met grep filteren, bijvoorbeeld met varnishlog | grep ReqURL om alleen de opgeroepen url’s te krijgen. Varnishstat levert een overzicht van waarden als de cachebelasting. Op basis van de waarde MAIN.n_lru_nuked kun je zien of de cache- RAM te klein is en Varnish gecachete objecten moet verwijderen.
Als de waarde 0 is, hoef je de cache niet te vergroten. Varnishhist toont een histogram dat de verdeling van de cache-hits en -misses laat zien. Varnishadm is een beheertool die de status en configuratie van de Varnishdaemon opvraagt en kan veranderen. Een overzicht van de meeste meldingen in de log krijg je met Varnishtop. Als je de door het programma geboden filterfuncties gebruikt, kun je bijvoorbeeld de meest bezochte webpagina’s of user-agents analyseren.
(Merlin Schumacher/Noud van Kruysbergen)