Slide 1

Slide 1 text

Goaze geven Deur Thijs Feryn met Varnish

Slide 2

Slide 2 text

Trage websites suckn

Slide 3

Slide 3 text

De mensjn en gèren rappe sites User Experience

Slide 4

Slide 4 text

No de kloten Trage ~ plat

Slide 5

Slide 5 text

Yo gastjes, 't is ier Thijs

Slide 6

Slide 6 text

165

Slide 7

Slide 7 text

'k Zien @ThijsFeryn ip Twitter

Slide 8

Slide 8 text

'k Zien Evanhelist bie

Slide 9

Slide 9 text

’k Weunen in Diksmude

Slide 10

Slide 10 text

Aan de Pluum’n

Slide 11

Slide 11 text

Juuste niet bachten de Kupe

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Mo money Mo servers Meer kluitn, meer servers

Slide 14

Slide 14 text

Cache

Slide 15

Slide 15 text

Nie herbereken ot niet veranderd is

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Geweunlijk Gebruker Server

Slide 18

Slide 18 text

With Varnish Gebruker Varnish Server

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Worom is 't zo goed?

Slide 21

Slide 21 text

Slimme kernel trucs

Slide 22

Slide 22 text

Bewoart HTTP output in't heheuhn*

Slide 23

Slide 23 text

Respecteert HTTP best practices

Slide 24

Slide 24 text

Varnish Configuration Language

Slide 25

Slide 25 text

Hoe scheid da met TLS/SSL?

Slide 26

Slide 26 text

't goat hier over Varnish 4 hé !

Slide 27

Slide 27 text

Installeern & configureern

Slide 28

Slide 28 text

apt-get install apt-transport-https curl https://repo.varnish-cache.org/GPG-key.txt | apt-key add - echo "deb https://repo.varnish-cache.org/debian/ jessie varnish-4.1"\ >> /etc/apt/sources.list.d/varnish-cache.list apt-get update apt-get install varnish Ip Debian Ubuntu & CentOS is ook meugelik

Slide 29

Slide 29 text

-a :80 \ -a :81,PROXY \ -T localhost:6082 \ -f /etc/varnish/default.vcl \ -S /etc/varnish/secret \ -s malloc,3g Simpele configuroasje

Slide 30

Slide 30 text

vcl 4.0; backend default { .host = "localhost"; .port = "8080"; } Minimale VCL

Slide 31

Slide 31 text

Varnish klapt HTTP

Slide 32

Slide 32 text

✓Idempotensje ✓Toestand ✓Vervallen ✓Conditionele requests ✓Cache varioasjes Varnish klapt HTTP

Slide 33

Slide 33 text

✓GET ✓HEAD -POST -PUT -PATCH -DELETE -TRACE -OPTIONS Idempotencsje Ollene GET & HEAD

Slide 34

Slide 34 text

✓Cacht gin cookies ✓Cacht gin set-cookies ✓Cacht gin Authorization headers Toestand User- specific content wordt standoard niet gecachet Helpt je hit rate no de kloten

Slide 35

Slide 35 text

Vervallen Expires: Sat, 09 Sep 2017 14:30:00 GMT Cache-control: public, max-age=3600, s-maxage=86400 Cache-control: private, no-cache, no-store

Slide 36

Slide 36 text

Voorrang 1. beresp.ttl (VCL) 2. s-maxage 3. max-age 4. expires 5. 120 seconden

Slide 37

Slide 37 text

Conditionele requests HTTP/1.1 200 OK Host: localhost Etag: 7c9d70604c6061da9bb9377d3f00eb27 Content-type: text/html; charset=UTF-8 Hello world output GET /if_none_match.php HTTP/1.1 Host: localhost User-Agent: curl/7.48.0

Slide 38

Slide 38 text

Conditionele requests HTTP/1.0 304 Not Modified Host: localhost Etag: 7c9d70604c6061da9bb9377d3f00eb27 GET /if_none_match.php HTTP/1.1 Host: localhost User-Agent: curl/7.48.0 If-None-Match: 7c9d70604c6061da9bb9377d3f00eb27

Slide 39

Slide 39 text

Conditionele requests HTTP/1.1 200 OK Host: localhost Last-Modified: Fri, 22 Jul 2016 10:11:16 GMT Content-type: text/html; charset=UTF-8 Hello world output GET /if_none_match.php HTTP/1.1 Host: localhost User-Agent: curl/7.48.0

Slide 40

Slide 40 text

Conditionele requests HTTP/1.0 304 Not Modified Host: localhost Last-Modified: Fri, 22 Jul 2016 10:11:16 GMT GET /if_none_match.php HTTP/1.1 Host: localhost User-Agent: curl/7.48.0 If-Modified-Since: Fri, 22 Jul 2016 10:11:16 GMT

Slide 41

Slide 41 text

✓Hostname (of IP) ✓URL Cache varioasjes Object identificeren in cache

Slide 42

Slide 42 text

Cache varioasjes GET / HTTP/1.1 Host: localhost Accept-Language: nl HTTP/1.1 200 OK Host: localhost Vary: Accept-Language Hallo, deze pagina is in het Nederlands geschreven.

Slide 43

Slide 43 text

Built-in VCL cheat sheet

Slide 44

Slide 44 text

✓Ollene GET & HEAD ✓Gin Cookie ✓Gin Authorization Built-in VCL (voorkant) Ipzoekn in cache Anders "pass" en nie cachen

Slide 45

Slide 45 text

✓Gin Set-Cookie ✓TTL > 0 ✓Gin "no-cache", "private", "no-store" Built-in VCL (achterkant) Ipsloan in cache Anders blacklist voe 120s

Slide 46

Slide 46 text

D'echte VCL code

Slide 47

Slide 47 text

sub vcl_recv { if (req.method == "PRI") { /* We do not support SPDY or HTTP/2.0 */ return (synth(405)); } if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } if (req.method != "GET" && req.method != "HEAD") { /* We only deal with GET and HEAD by default */ return (pass); } if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } return (hash); }

Slide 48

Slide 48 text

sub vcl_pipe { # By default Connection: close is set on all piped requests, to stop # connection reuse from sending future requests directly to the # (potentially) wrong backend. If you do want this to happen, you can undo # it here. # unset bereq.http.connection; return (pipe); } sub vcl_pass { return (fetch); } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (lookup); }

Slide 49

Slide 49 text

sub vcl_purge { return (synth(200, "Purged")); } sub vcl_hit { if (obj.ttl >= 0s) { // A pure unadultered hit, deliver it return (deliver); } if (obj.ttl + obj.grace > 0s) { // Object is in grace, deliver it // Automatically triggers a background fetch return (deliver); } // fetch & deliver once we get the result return (miss); } sub vcl_miss { return (fetch); } sub vcl_deliver { return (deliver); }

Slide 50

Slide 50 text

sub vcl_backend_fetch { return (fetch); } sub vcl_backend_response { if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Surrogate-control ~ "no-store" || (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "no-cache|no- store|private") || beresp.http.Vary == "*") { /* * Mark as "Hit-For-Pass" for the next 2 minutes */ set beresp.ttl = 120s; set beresp.uncacheable = true; } return (deliver); }

Slide 51

Slide 51 text

De werkelijkheid suckt

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

Cache-control ?

Slide 55

Slide 55 text

Oede briel

Slide 56

Slide 56 text

Schrieft VCL

Slide 57

Slide 57 text

Normaliseren

Slide 58

Slide 58 text

vcl 4.0; import std; sub vcl_recv { set req.http.Host = regsub(req.http.Host, ":[0-9]+", ""); set req.url = std.querysort(req.url); if (req.url ~ "\#") { set req.url = regsub(req.url, "\#.*$", ""); } if (req.url ~ "\?$") { set req.url = regsub(req.url, "\?$", ""); } if (req.restarts == 0) { if (req.http.Accept-Encoding) { if (req.http.User-Agent ~ "MSIE 6") { unset req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } elsif (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; } else { unset req.http.Accept-Encoding; } } } }

Slide 59

Slide 59 text

sub vcl_recv { if (req.url ~ "^/status\.php$" || req.url ~ "^/update\.php$" || req.url ~ "^/admin$" || req.url ~ "^/admin/.*$" || req.url ~ "^/user$" || req.url ~ "^/user/.*$" || req.url ~ "^/flag/.*$" || req.url ~ "^.*/ajax/.*$" || req.url ~ "^.*/ahah/.*$") { return (pass); } } URL blacklist

Slide 60

Slide 60 text

sub vcl_recv { if (req.url ~ "^/products/?" return (hash); } } URL whitelist

Slide 61

Slide 61 text

Koekn

Slide 62

Slide 62 text

vcl 4.0; sub vcl_recv { set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", ""); if (req.http.cookie ~ "^\s*$") { unset req.http.cookie; } } Tracking cookies wegdoen

Slide 63

Slide 63 text

vcl 4.0; sub vcl_recv { if (req.http.Cookie) { set req.http.Cookie = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.cookie ~ "^\s*$") { unset req.http.cookie; } } } Ollene session cookie bewoaren

Slide 64

Slide 64 text

sub vcl_recv { if (req.http.Cookie) { set req.http.Cookie = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(language)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.cookie ~ "^\s*$") { unset req.http.cookie; return(pass); } return(hash); } } sub vcl_hash { hash_data(regsub( req.http.Cookie, "^.*language=([^;]*);*.*$", "\1" )); } Cache variaosje op language cookie

Slide 65

Slide 65 text

Of gebruukt vmod_cookie

Slide 66

Slide 66 text

Alternatieve taal cache varioasje

Slide 67

Slide 67 text

sub vcl_hash { hash_data(req.http.Accept-Language); } HTTP/1.1 200 OK Host: localhost Vary: Accept-Language Hash de tale Of gebruukt

Slide 68

Slide 68 text

Wuk doej met koekn?

Slide 69

Slide 69 text

✓Nie olles in een session smietn ✓Gebruukt vaste cookies ✓Doe tracking cookies weg uut VCL ✓Gebruukt cookies in VCL voe beslissingen te pakn ✓Cache varioasjes met cookies ✓Gebruukt ollene mo session cookies ot echt nodig is ✓Gebruikt JWT voe session state client- side ip te sloan Wuk doej met koekn?

Slide 70

Slide 70 text

Blokn cachen

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

Code spuugt één HTTP response uut

Slide 73

Slide 73 text

Bie gevolg: nie cachen

Slide 74

Slide 74 text

Edge Side Includes ✓Placeholder ✓Geparsed deur Varnish ✓Output is è compoziesje van blokn ✓Toestand per blok ✓TTL per blok

Slide 75

Slide 75 text

sub vcl_recv { set req.http.Surrogate-Capability = "key=ESI/1.0"; } sub vcl_backend_response { if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; } } Edge Side Includes

Slide 76

Slide 76 text

ESI vergeleken met AJAX

Slide 77

Slide 77 text

Peist goed, kiest verstandig ESI, geparsed duer Varnish HInclude, geparsed deur Javascript

Slide 78

Slide 78 text

Druk ip de ketel

Slide 79

Slide 79 text

✓Varnishlog ✓Varnishtop ✓Varnishstat Druk ip de ketel

Slide 80

Slide 80 text

Nieuws dat er niet deure komt

Slide 81

Slide 81 text

Purge

Slide 82

Slide 82 text

acl purge { "localhost"; "127.0.0.1"; "::1"; } sub vcl_recv { if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405, “Not allowed.”)); } return (purge); } } Purge

Slide 83

Slide 83 text

acl purge { "localhost"; "127.0.0.1"; "::1"; } sub vcl_backend_response { set beresp.http.x-url = bereq.url; set beresp.http.x-host = bereq.http.host; } sub vcl_deliver { unset resp.http.x-url; unset resp.http.x-host; } sub vcl_recv { if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405, "Not allowed")); } if(req.http.x-purge-regex) { ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url ~ " + req.http.x-purge-regex); } else { ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url == " + req.url); } return (synth(200, "Purged")); } } Ban

Slide 84

Slide 84 text

Ban curl -XPURGE "http://example.com/products" curl -XPURGE -H "x-purge-regex:/products" \ "http://example.com" varnishadm> ban obj.http.x-host == example.com && obj.http.x-url ~ ^/product/[0-9]+/details

Slide 85

Slide 85 text

Minder VCL Betere code

Slide 86

Slide 86 text

https://github.com/ThijsFeryn/ cacheable-site-silex/tree/v2

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

https://twitter.com/thijsferyn https://instagram.com/thijsferyn https://blog.feryn.eu https://talks.feryn.eu https://book.feryn.eu https://youtube.com/thijsferyn https://soundcloud.com/thijsferyn http://itunes.feryn.eu