Share
Embed
Varnish In Action
Slides for my Varnish talk at PHP North West 2012
Thijs Feryn PRO
October 06, 2012
Transcript
101 slides
-
Expires: Sun, 25 Jun 2006 14:57:12 Cache-‐Control: max-‐age=86400,
must-‐revalidate Expira>on -
Last-‐Modified: Sun, 25 Jun 2006 14:57:12 GMT ETag: “686897696a7c876b7e” Compared
with the “If-‐None-‐ Match” header. Throws “HTTP/1.0 304 Not Modified” accordingly Invalida>on -
curl http://repo.varnish-‐cache.org/debian/GPG-‐ key.txt | apt-‐key add -‐ apt-‐get update echo
"deb http://repo.varnish-‐cache.org/ debian/ squeeze varnish-‐3.0" >> /etc/apt/ sources.list apt-‐get install varnish -
DAEMON_OPTS="-‐a :80 \ -‐T localhost:6082 \ -‐f /etc/varnish/default.vcl \ -‐S
/etc/varnish/secret \ -‐s malloc,256m" In “/etc/default/varnish” Install & configure -
backend default { .host =
"127.0.0.1"; .port = "8080"; } In “/etc/varnish/default.vcl” Backend -
Only get & HEAD No cookie & auth headers No
set-cookie headers cache ttl > 0 No vary “*” When will varnish cache? -
About cookies HTTP cookie request header via browser HTTP set-cookie
response header via webserver -
based on host/ip + urL hash By default in Memory
Optionally on disk how will varnish cache? -
4+05:26:25 Hitrate ratio: 10
100 254 Hitrate avg: 0.8486 0.7619 0.7285 1760818 6.99 4.82 client_conn -‐ Client connections accepted 11088687 25.96 30.36 client_req -‐ Client requests received 8042715 11.98 22.02 cache_hit -‐ Cache hits 2609561 11.98 7.15 cache_miss -‐ Cache misses 47104 1.00 0.13 backend_conn -‐ Backend conn. success 610 0.00 0.00 backend_fail -‐ Backend conn. failures 2998265 12.98 8.21 backend_reuse -‐ Backend conn. reuses 12081 0.00 0.03 backend_toolate -‐ Backend conn. was closed 3010356 13.98 8.24 backend_recycle -‐ Backend conn. recycles 13 0.00 0.00 backend_retry -‐ Backend conn. retry 520 0.00 0.00 fetch_head -‐ Fetch head 2857965 11.98 7.83 fetch_length -‐ Fetch with Length 151309 2.00 0.41 fetch_chunked -‐ Fetch chunked 4404 0.00 0.01 fetch_close -‐ Fetch wanted close 676 0.00 0.00 fetch_failed -‐ Fetch failed 31164 0.00 0.09 fetch_304 -‐ Fetch no body (304) 220 . . n_sess_mem -‐ N struct sess_mem 53 . . n_sess -‐ N struct sess 29540 . . n_object -‐ N struct object 29561 . . n_objectcore -‐ N struct objectcore 5058 . . n_objecthead -‐ N struct objecthead 2613 . . n_waitinglist -‐ N struct waitinglist 3 . . n_vbc -‐ N struct vbc 22 . . n_wrk -‐ N worker threads 1789 0.00 0.00 n_wrk_create -‐ N worker threads created -
12 SessionOpen c 172.16.26.1 50396 :8080
12 ReqStart c 172.16.26.1 50396 668213522 12 RxRequest c GET 12 RxURL c /test.php 12 RxProtocol c HTTP/1.1 12 RxHeader c Host: varnish.dev:8080 12 RxHeader c User-‐Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; nl; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 12 RxHeader c Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8 12 RxHeader c Accept-‐Language: nl,en-‐us;q=0.7,en;q=0.3 12 RxHeader c Accept-‐Encoding: gzip,deflate 12 RxHeader c Accept-‐Charset: ISO-‐8859-‐1,utf-‐8;q=0.7,*;q=0.7 12 RxHeader c Keep-‐Alive: 115 12 RxHeader c Connection: keep-‐alive 12 RxHeader c Cookie: PHPSESSID=2n2pkit81qdgk6k4trf1crft16 12 VCL_call c recv 12 VCL_return c pass 12 VCL_call c hash 12 VCL_return c hash 12 VCL_call c pass 12 VCL_return c pass 14 BackendClose -‐ default 14 BackendOpen b default 127.0.0.1 34267 127.0.0.1 80 12 Backend c 14 default default -
Examples varnishlog -‐c -‐m"VCL_call:hit" | grep RxURL varnishlog -‐c -‐m"VCL_call:miss"
| grep RxURL varnishlog -‐a -‐w /tmp/varnish.log varnishlog -‐r /tmp/varnish.log varnishlog -‐i RxHeader -‐I Cookie -
list length 20 107.57 RxHeader
User-‐Agent: Mozilla/5.0 (Windows NT 6.1; W 101.96 RxHeader User-‐Agent: Mozilla/5.0 (Windows NT 6.1; W 82.49 RxHeader User-‐Agent: Mozilla/4.0 (compatible; MSIE 69.90 RxHeader User-‐Agent: Mozilla/5.0 (compatible; MSIE 64.04 RxHeader User-‐Agent: Mozilla/5.0 (Windows NT 6.1; W 43.74 RxHeader User-‐Agent: Mozilla/4.0 (compatible; MSIE 22.01 RxHeader User-‐Agent: Mozilla/5.0 (iPod; U; CPU iPho 21.43 RxHeader User-‐Agent: Mozilla/4.0 (compatible; MSIE 19.86 RxHeader User-‐Agent: Mozilla/5.0 (X11; Linux x86_64 15.47 RxHeader User-‐Agent: Mozilla/5.0 (Windows NT 6.1; W 12.96 RxHeader User-‐Agent: Mozilla/5.0 (Windows NT 6.1; W 4.87 RxHeader User-‐Agent: Mozilla/4.0 (compatible; MSIE 2.97 RxHeader User-‐Agent: Mozilla/5.0 (compatible; MSIE 2.75 RxHeader User-‐Agent: Mozilla/5.0 (Windows NT 6.1; W 2.56 RxHeader User-‐Agent: Mozilla/5.0 (Windows NT 6.1; r 0.97 RxHeader User-‐Agent: Mozilla/5.0 (Windows; U; Windo 0.86 RxHeader User-‐Agent: Mozilla/5.0 (iPhone; CPU iPhon 0.83 RxHeader User-‐Agent: Mozilla/5.0 (Windows; U; Windo 0.53 RxHeader User-‐Agent: Mozilla/5.0 (compatible; Googl 0.44 RxHeader User-‐Agent: Mozilla/4.0 (compatible;) -
Examples varnishtop -‐i RxHeader -‐I \^User-‐Agent varnishtop -‐i RxRequest varnishtop
-‐i RxHeader -‐I \^Host varnishtop -‐i RxHeader -‐I Cookie -
Example varnishncsa -‐D -‐a -‐w /var/log/some.log 172.16.26.1 -‐ -‐ [19/Oct/2010:16:08:02
+0200] "GET http://varnish.dev:8080/ HTTP/1.1" 200 97 "-‐" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; nl; rv:1.9.2.10) Gecko/20100914 Firefox/ 3.6.10" -
Telnet management root@dev:/# telnet localhost 6082 Trying ::1... Connected to
localhost. Escape character is '^]'. 200 154 -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ Varnish HTTP accelerator CLI. -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ Type 'help' for command list. Type 'quit' to close CLI session. -
# sub vcl_recv { # if
(req.restarts == 0) { # if (req.http.x-‐forwarded-‐for) { # set req.http.X-‐Forwarded-‐For = # req.http.X-‐Forwarded-‐For + ", " + client.ip; # } else { # set req.http.X-‐Forwarded-‐For = client.ip; # } # } # if (req.request != "GET" && # req.request != "HEAD" && # req.request != "PUT" && # req.request != "POST" && # req.request != "TRACE" && # req.request != "OPTIONS" && # req.request != "DELETE") { # /* Non-‐RFC2616 or CONNECT which is weird. */ # return (pipe); # } # if (req.request != "GET" && req.request != "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 (lookup); # } -
# sub vcl_hash { # hash_data(req.url);
# if (req.http.host) { # hash_data(req.http.host); # } else { # hash_data(server.ip); # } # return (hash); # } # sub vcl_fetch { # if (beresp.ttl <= 0s || # beresp.http.Set-‐Cookie || # beresp.http.Vary == "*") { # /* # * Mark as "Hit-‐For-‐Pass" for the next 2 minutes # */ # set beresp.ttl = 120 s; # return (hit_for_pass); # } # return (deliver); # } -
Cache sta>c files sub vcl_recv{ if((req.request == "GET" ||
req.request == "HEAD") && req.url ~ "\. (png|gif|jpe?g|swf|css|js|html?|sstm) $" ){ return(lookup); } else { return(pass); } } -
Custom hit/miss marker sub vcl_deliver { if (obj.hits >
0) { set resp.http.X-‐Varnish-‐Cache = "HIT"; } else { set resp.http.X-‐Varnish-‐Cache = "MISS"; } } -
Set TTL sub vcl_fetch { if(req.url ~
"^/bla") { set beresp.ttl = 10s; } else { set beresp.ttl = 3600s; } } -
Remove client cookies sub vcl_recv { unset
req.http.cookie; } Remove server cookies sub vcl_fetch { unset beresp.http.set-‐cookie; } -
Remove GA cookies sub vcl_recv { if (req.http.Cookie) {
set req.http.Cookie = regsuball(req.http.Cookie,"(^|; ) *__utm.=[^;]+;? *","\1"); if (req.http.Cookie == "") { remove req.http.Cookie; } } -
Ignore cookies sub vcl_recv { if (req.request ==
"GET" || req.request == "HEAD") { return (lookup); } } Ignores default behaviour -
Add cookies to hash sub vcl_recv { if
(req.request == "GET" || req.request == "HEAD") { return (lookup); } } sub vcl_hash { hash_data(req.http.cookie); } All cookies -
Add a specific cookie to hash sub vcl_recv {
if (!req.http.Cookie ~ "country") { return(pass); } } sub vcl_hash { if(req.http.Cookie ~ "country"){ hash_data(regsuball(req.http.Cookie, "^.+;? ? country=([a-‐zA-‐Z0-‐9]+)( |;| ;).*$","\1")); } } -
Choose a backend backend default { .host
= "default.server.com"; .port = "80"; } backend other { .host = "other.server.com"; .port = "80"; } sub vcl_recv { if(req.http.host ~ "^www\."){ set req.backend= default; } else { set req.backend = other; } } -
Load balancing backend default { .host =
"default.server.com"; .port = "80"; .probe = { .url = "/"; .timeout = 50 ms; .interval = 1s; .window = 2; .threshold = 2; } } backend other { .host = "other.server.com"; .port = "80"; .probe = { .url = "/"; .timeout = 50 ms; .interval = 1s; .window = 2; .threshold = 2; } } -
Director for load balancing director back random { {.backend
= default; .weight=1;} {.backend = other; .weight=2;} } sub vcl_recv { set req.backend = back; return(pass); } -
Grace mode sub vcl_recv { if (req.backend.healthy)
{ set req.grace = 1s; } else { set req.grace = 10s; } } Keep reading from cache, even when expired -
ACL & purge acl purge { "localhost"; "192.0.2.1"/24;
} sub vcl_recv { if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } return(lookup); } } sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged."; } } sub vcl_miss { if (req.request == "PURGE") { purge; error 200 "Purged."; } } Or 404 curl -‐X PURGE h]p://yoursite.com/yourpage -
Purge & vcl_hash Purge only works with the standard
vcl_hash implementa>on sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (hash); } -
Purge & vcl_hash Doesn’t work with custom vcl_hash sub vcl_hash
{ if(req.http.Cookie ~ "country"){ hash_data(req.http.Cookie); } } -
Ban sub vcl_hit { if (req.request == "PURGE") {
ban("req.url ~ " + req.url + " && req.http.host == " + req.http.host); error 200 "Purged."; } } sub vcl_miss { if (req.request == "PURGE") { ban("req.url ~ " + req.url + " && req.http.host == " + req.http.host); error 200 "Purged."; } } -
Vary header Vary: Cookie Tells the proxy what extra fields
to use for caching Remove unnecessary cookies in vcl_recv Watch out for browser cache -
Vary header Vary: X-‐Cookie Don’t vary the cookie or Internet
Explorer will go nuts Vary on custom header -
Vary header sub vcl_recv { set req.http.X-‐Cookie =
req.http.cookie } -
<html> <body> <table> <tr> <td colspan="2" > <?php include('header.php') ?>
</td> </tr> <tr> <td><?php include('menu.php') ?></td> <td><?php include('main.php') ?></td> </tr> <tr> <td colspan="2" > <?php include('footer.php') ?> </td> </tr> </table> </body> </html> -
<html> <body> <table> <tr> <td colspan="2" > <esi:include src="/header.php" />
</td> </tr> <tr> <td><esi:include src="/menu.php" /></td> <td><esi:include src="/main.php" /></td> </tr> <tr> <td colspan="2" > <esi:include src="/footer.php" /> </td> </tr> </table> </body> -
<html> <body> <table> <tr> <td colspan="2" > <esi:include src="/header.php" />
</td> </tr> <tr> <td><esi:include src="/menu.php" /></td> <td><esi:include src="/main.php" /></td> </tr> <tr> <td colspan="2" > <esi:include src="/footer.php" /> </td> </tr> </table> </body> -
<?php function esi($file){ if(isset($_SERVER['Surrogate-Capability']) && preg_match('/^(.+)="ESI/1.0$/',$_SERVER['Surrogate-Capability'])){ header("Surrogate-Control: content='ESI/1.0'"); $url =
'http://'. $_SERVER['HTTP_HOST'].substr($_SERVER['SCRIPT_NAME'], 0,1+strrpos($_SERVER['SCRIPT_NAME'],'/')).$file; echo "<esi:include src=\"$url\" />".PHP_EOL; } else { include($file); } } ESI PHP helper funcXon -
<?php include('esi.php'); ?> <html> <body> <table> <tr> <td colspan="2" >
<?php echo esi('header.php'); ?> </td> </tr> <tr> <td><?php echo esi('menu.php'); ?></td> <td><?php echo esi('main.php'); ?></td> </tr> <tr> <td colspan="2" > <?php echo esi('footer.php'); ?> </td> </tr> </table> </body> </html> -
ESI VCL sub vcl_recv { set req.http.Surrogate-‐Capability="key=ESI/1.0";
} sub vcl_fetch { if(beresp.http.Surrogate-‐Control~"ESI/1.0") { unset beresp.http.Surrogate-‐Control; set beresp.do_esi=true; } }