C.R.E.A.M. (Cache Rules Everything Around Me) - TEK13

C.R.E.A.M. (Cache Rules Everything Around Me) - TEK13

Slides for my Cache Rules Everything Around Me talk at TEK13 in Chicago

Ca901ddcea38854b9783781c91fc87c9?s=128

Thijs Feryn

May 16, 2013
Tweet

Transcript

  1. C.R.E.A.M CASH RULES EVERYTHING AROUND ME CACHE Thijs Feryn

  2. Hi# my#name# is#Thijs

  3. I’m# an#evangelist#at

  4. I’m# a#board#member# at

  5. None
  6. None
  7. Old school Don’t# store#anything# you#can# recalculate

  8. Old school Store/cache to avoid recalculation

  9. Protect your infrastructure

  10. Responsibilities

  11. Tear down silos

  12. Fundamentals

  13. None
  14. Browser#cache Page#cache Internal#data#cache Opcode#cache

  15. None
  16. Cache@control Cache&Control,“max&age=3600,,s& maxage=1000,,public,,must&revalidate”

  17. Expires Expires,"Wed,,1,Jan,2014,20:00:00,GMT"

  18. ETag If&None&Match:,"3e86&410&3596Obc" ETag:,"3e86&410&3596Obc"

  19. Problems

  20. None
  21. Lexing Source, to,tokens Tokenizing Interpre4ng, tokens Compiling Generate, byte,code Execu4on

    Run, byte,code
  22. Lexing Tokenizing Compiling Cache, byte,code Execu4on Run, byte,code Opcode,caching

  23. Zend#Optimizer#(plus) Eaccelerator XCache APC

  24. None
  25. Which direction are we heading?

  26. Zend Optimizer + APCu https://github.com/zend-dev/ZendOptimizerPlus https://github.com/krakjoe/apcu

  27. Caching internal data

  28. Compensate for expensive calls ✓RDBMS ✓Webservice ✓Feed ✓Other external resource

  29. APC User% func*ons

  30. <?php apc_add('key1','This is key1', 10); apc_add('key2','This is key2'); apc_add('key3',2); apc_delete('key2');

    apc_store('key2','bla',12); var_dump( apc_exists('key1'), apc_exists(array('key2','key3')), apc_inc('key3'), apc_dec('key3',12), apc_fetch('key1'), apc_clear_cache('user'), apc_fetch('key1') );
  31. <?php var_dump(apc_sma_info()); array(4) { ["num_seg"]=> int(1) ["seg_size"]=> float(33554352) ["avail_mem"]=> float(29335064)

    ["block_lists"]=> array(1) { [0]=> array(1) { [0]=> array(2) { ["size"]=> int(29335040) ["offset"]=> int(4219344) } } } }
  32. Memcached

  33. Memcached ✓Key value store ✓Distributed cache ✓Over TCP/IP ✓Stored in

    memory ✓Fast ✓Client-side intelligence
  34. <?php try{ $m = new Memcached(); $m->addServer('localhost',11211); if($m->add('key1','value1',10) === false){

    throw new Exception($m->getResultMessage()); } if($m->set('key2','value2',10) === false){ throw new Exception($m->getResultMessage()); } if($m- >setMulti(array('key3'=>'value3','key4'=>'value4'), 10) === false){ throw new Exception($m->getResultMessage()); } } catch(Exception $e) { echo "Error: ".$e.PHP_EOL; } Create
  35. <?php $m = new Memcached(); $m->addServer('localhost',11211); $value1 = $m->get('key1'); $result

    = $m->getMulti(array('key2','key3','key4')); var_dump($value1,$result); Retrieve
  36. <?php try{ $m = new Memcached(); $m->addServer('localhost',11211); if($m->set('key1','value1',10) === false){

    throw new Exception($m->getResultMessage()); } if($m->replace('key1','azerty',10) === false){ throw new Exception($m->getResultMessage()); } if($m- >setMulti(array('key1'=>'value1','key2'=>'value2'), 10) === false){ throw new Exception($m->getResultMessage()); } } catch(Exception $e) { echo "Error: ".$e.PHP_EOL; } Update
  37. <?php try{ $m = new Memcached(); $m->addServer('localhost',11211); if($m->delete('key1') === false){

    throw new Exception($m->getResultMessage()); } if($m- >deleteMulti(array('key2','key3','key4')) === false){ throw new Exception($m->getResultMessage()); } } catch(Exception $e) { echo "Error: ".$e.PHP_EOL; } Delete
  38. <?php $m = new Memcached(); //$m- >setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT); $m->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE,true); $servers =

    array( array('localhost', 11211), array('localhost', 11212), array('localhost', 11213) ); $m->addServers($servers); for($i=0; $i<10;$i++){ if(($value = $m->get($i)) === false){ $value = date('Y-m-d H:i:s'); $m->set($i, $value); echo "<strong>$i</strong> not in cache, setting to $value <br / >".PHP_EOL; echo "Error: ".$m->getResultMessage()." (".$m->getResultCode().")<hr / >".PHP_EOL; } else { echo "Value for <strong>$i</strong>: $value <br />".PHP_EOL; } } High availability
  39. Memcached memcached.sess_prefix = "memc.sess.key." session.save_path="127.0.0.1:11211" session.save_handler = memcached Also, for,session,

    handling
  40. None
  41. ✓Just like Memcached ✓Replication ✓Disk persistence ✓Data structures ✓Transactions ✓More

    partitioning options ✓PubSub
  42. Keys <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379, 'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->set('key1', 'This is key1'); $client->expire('key1',10); $client->expire('key2',10); $client->set('key2', 'This is key2'); $client->persist('key2'); $client->set('key3', 'This is key3'); $client->del('key3'); $client->rename('key2','key3'); var_dump( $client->keys('k*'), $client->get('key1'), $client->exists('key3'), $client->ttl('key1'), $client->type('key1') );
  43. Strings <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379, 'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->set('key1', 'This is key1'); $client->setex('key2', 10, 'This is key2'); $client->set('key3', 1); $client->incr('key3'); $client->incrby('key3',2); $client- >mset('key4','This is key4','key5','This is key5'); var_dump( $client->strlen('key1'), $client->ttl('key2'), $client->getset('key1','New value for key1'), $client->get('key1'), $client->mget('key4','key5') );
  44. Hashes <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379,'data base'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->hset('hash1', 'name', 'Name for hash1'); $client->hmset('hash1', 'id', 1, 'status','ok'); $client->hset('hash2', 'name', 'Name for hash2'); $client->hsetnx('hash2', 'id', 1); $client->hincrby('hash3','id',1); $client->hset('hash2', 'bla', 'bla'); $client->hdel('hash2','bla'); var_dump( $client->hexists('hash1','id'), $client->hget('hash1','id'), $client->hgetall('hash1'), $client->hkeys('hash2'), $client->hvals('hash2'), $client->hlen('hash2'), $client->hmget('hash1','id','name') );
  45. Lists <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379, 'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->rpush('list1', 'b', 'c', 'e','f','g'); $client->lpush('list1','a'); $client->linsert('list1','BEFORE','e','d'); $client->ltrim('list1',0,2); var_dump( $client->lindex('list1',0), $client->llen('list1'), $client->lpop('list1'), $client->lrange('list1',0,2) );
  46. Sets <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379 ,'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->sadd('set1','a','b','c',3,5,1); $client->sadd('set2',0,1,2); $client->smove('set1','set2',3); $client->srem('set1',5); var_dump( $client->scard('set1'), $client->smembers('set1'), $client->sismember('set1','f'), $client->srandmember('set1',2), $client->sinter('set1','set2'), $client->sdiff('set1','set2'), $client->sunion('set1','set2') );
  47. session.save_handler = redis session.save_path = "tcp://host1:6379? weight=1, tcp://host2:6379? weight=2&timeout=2.5, tcp://host3:6379?

    weight=2" Also, for,session, handling Requires, phpredis,PECL, module
  48. Page caching

  49. RewriteEngine*On RewriteCond*%{REQUEST_FILENAME}*=s*[OR] RewriteCond*%{REQUEST_FILENAME}*=l*[OR] RewriteCond*%{REQUEST_FILENAME}*=d RewriteRule*^.*$*=*[NC,L] RewriteRule*^.*$*index.php*[NC,L] Apache# mod_rewrite

  50. " location / { try_files $uri $uri/ /index.php; } Nginx

  51. <?php require('db.php'); $data = db_get_content_from_uri( $_SERVER['REQUEST_URI']); $fp = fopen(dirname(__FILE__). $_SERVER['REQUEST_URI'],

    'w'); fwrite($fp, $data); fclose($fp); echo $data; Write#to#file# &#print
  52. [PHP] auto_prepend_file*“/path/to/prepend.php” auto_append_file*“/path/to/append.php” Auto# execute#before# &#after#each# script

  53. <?php if($_SERVER['REQUEST_METHOD'] == 'GET'){ $key = md5('http://'.$_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI']); if(($output =

    apc_fetch($key)) !== false){ echo $output; exit(); } ob_start(); } Prepend
  54. <?php if($_SERVER['REQUEST_METHOD'] == 'GET'){ $output = ob_get_contents(); ob_end_clean(); $key =

    md5('http://'.$_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI']); apc_store($key,$output,20); echo $output; } Append
  55. File MySQL APC Memcached Redis

  56. Avoid#slow# parts#of#your#PHP# application

  57. Avoid# PHP#runtime# entirely

  58. Reverse proxy

  59. Varnish

  60. backend(default({ ((((((.host(=("127.0.0.1"; ((((((.port(=("8080"; } In#“/etc/varnish/default.vcl” Backend

  61. Out of the box

  62. Only get & HEAD No cookie & auth headers No

    set-cookie headers cache ttl > 0 No vary “*” When will varnish cache?
  63. Request vcl_recv In cache? vcl_hash Cacheable? vcl_hit() vcl_miss() vcl_deliver() vcl_fetch()

    No Yes No Yes Response
  64. 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); }
  65. sub vcl_pipe { # Note that only the first request

    to the backend will have # X-Forwarded-For set. If you use X-Forwarded-For and want to # have it set for all requests, make sure to have: # set bereq.http.connection = "close"; # here. It is not set by default as it might break some broken web # applications, like IIS with NTLM authentication. return (pipe); } sub vcl_pass { return (pass); } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (hash); }
  66. sub vcl_hit { return (deliver); } sub vcl_miss { return

    (fetch); } 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); } sub vcl_deliver { return (deliver); }
  67. sub vcl_error { set obj.http.Content-Type = "text/html; charset=utf-8"; set obj.http.Retry-After

    = "5"; synthetic {" <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>"} + obj.status + " " + obj.response + {"</title> </head> <body> <h1>Error "} + obj.status + " " + obj.response + {"</h1> <p>"} + obj.response + {"</p> <h3>Guru Meditation:</h3> <p>XID: "} + req.xid + {"</p> <hr> <p>Varnish cache server</p> </body> </html> "}; return (deliver); } sub vcl_init { " return (ok); } sub vcl_fini { " return (ok); }
  68. Monitoring & Logging

  69. Varnishstat

  70. 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
  71. Varnishlog

  72. ***11*SessionOpen**c*12.12.12.1*53727*:80 ***11*ReqStart*****c*12.12.12.1*53727*1401010767 ***11*RxRequest****c*GET ***11*RxURL********c*/ ***11*RxProtocol***c*HTTP/1.1 ***11*RxHeader*****c*Host:*12.12.12.6 ***11*RxHeader*****c*User=Agent:*Mozilla/5.0*(Macintosh;*Intel*Mac*OS*X*10.8;*rv:17.0)* Gecko/20100101*Firefox/17.0 ***11*RxHeader*****c*Accept:*text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8

    ***11*RxHeader*****c*Accept=Language:*nl,en;q=0.7,fr=be;q=0.3 ***11*RxHeader*****c*Accept=Encoding:*gzip,*deflate ***11*RxHeader*****c*Connection:*keep=alive ***11*VCL_call*****c*recv*lookup ***11*VCL_call*****c*hash ***11*Hash*********c*/ ***11*Hash*********c*12.12.12.6 ***11*VCL_return***c*hash ***11*VCL_call*****c*miss*fetch ***11*Backend******c*13*default*default ***11*TTL**********c*1401010767*RFC*0*=1*=1*1357920021*0*1357920020*0*0 ***11*VCL_call*****c*fetch ***11*TTL**********c*1401010767*VCL*120*=1*=1*1357920021*=0 ***11*VCL_return***c*hit_for_pass ***11*ObjProtocol**c*HTTP/1.1 ***11*ObjResponse**c*OK ***11*ObjHeader****c*Date:*Fri,*11*Jan*2013*16:00:20*GMT ***11*ObjHeader****c*Server:*Apache ***11*ObjHeader****c*X=Powered=By:*PHP/5.3.2=1ubuntu4.18 ***11*ObjHeader****c*Cache=Control:*no=cache,*no=store,*max=age=0 Client%
  73. ***11*VCL_return***c*hit_for_pass ***11*ObjProtocol**c*HTTP/1.1 ***11*ObjResponse**c*OK ***11*ObjHeader****c*Date:*Fri,*11*Jan*2013*16:00:20*GMT ***11*ObjHeader****c*Server:*Apache ***11*ObjHeader****c*X=Powered=By:*PHP/5.3.2=1ubuntu4.18 ***11*ObjHeader****c*Cache=Control:*no=cache,*no=store,*max=age=0 ***11*ObjHeader****c*Vary:*Accept=Encoding ***11*ObjHeader****c*Content=Encoding:*gzip ***11*ObjHeader****c*Content=Length:*119

    ***11*ObjHeader****c*Content=Type:*text/html ***11*Gzip*********c*u*F*=*119*336*80*80*887 ***11*VCL_call*****c*deliver*deliver ***11*TxProtocol***c*HTTP/1.1 ***11*TxStatus*****c*200 ***11*TxResponse***c*OK ***11*TxHeader*****c*Server:*Apache ***11*TxHeader*****c*X=Powered=By:*PHP/5.3.2=1ubuntu4.18 ***11*TxHeader*****c*Cache=Control:*no=cache,*no=store,*max=age=0 ***11*TxHeader*****c*Vary:*Accept=Encoding ***11*TxHeader*****c*Content=Encoding:*gzip ***11*TxHeader*****c*Content=Type:*text/html ***11*TxHeader*****c*Content=Length:*119 ***11*TxHeader*****c*Accept=Ranges:*bytes ***11*TxHeader*****c*Date:*Fri,*11*Jan*2013*16:00:20*GMT ***11*TxHeader*****c*X=Varnish:*1401010767 ***11*TxHeader*****c*Age:*0 ***11*TxHeader*****c*Via:*1.1*varnish ***11*TxHeader*****c*Connection:*keep=alive ***11*Length*******c*119 ***11*ReqEnd*******c*1401010767*1357920020.712090731*1357920020.727306366*0.000087738* Client%
  74. ***13*BackendClose*=*default ***13*BackendOpen**b*default*127.0.0.1*51597*127.0.0.1*8080 ***13*TxRequest****b*GET ***13*TxURL********b*/ ***13*TxProtocol***b*HTTP/1.1 ***13*TxHeader*****b*Host:*12.12.12.6 ***13*TxHeader*****b*User=Agent:*Mozilla/5.0*(Macintosh;*Intel*Mac*OS*X*10.8;*rv:17.0)* Gecko/20100101*Firefox/17.0 ***13*TxHeader*****b*Accept:*text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8

    ***13*TxHeader*****b*Accept=Language:*nl,en;q=0.7,fr=be;q=0.3 ***13*TxHeader*****b*X=Forwarded=For:*12.12.12.1 ***13*TxHeader*****b*X=Varnish:*1401010767 ***13*TxHeader*****b*Accept=Encoding:*gzip ***13*RxProtocol***b*HTTP/1.1 ***13*RxStatus*****b*200 ***13*RxResponse***b*OK ***13*RxHeader*****b*Date:*Fri,*11*Jan*2013*16:00:20*GMT ***13*RxHeader*****b*Server:*Apache ***13*RxHeader*****b*X=Powered=By:*PHP/5.3.2=1ubuntu4.18 ***13*RxHeader*****b*Cache=Control:*no=cache,*no=store,*max=age=0 ***13*RxHeader*****b*Vary:*Accept=Encoding ***13*RxHeader*****b*Content=Encoding:*gzip ***13*RxHeader*****b*Content=Length:*119 ***13*RxHeader*****b*Content=Type:*text/html ***13*Fetch_Body***b*4(length)*cls*0*mklen*1 ***13*Length*******b*119 ***13*BackendReuse*b*default Backend%
  75. varnishlog -c -m VCL_call:hit | grep -i 'RxURL' Varnishlog varnishlog

    -b -i TxURL Hits Misses
  76. Cache,staWc,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); **}

    }
  77. 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"; **} }

  78. Set,TTL sub*vcl_fetch*{ ****if(req.url*~*"^/bla")*{ ********set*beresp.ttl*=*10s; ****}*else*{ ********set*beresp.ttl*=*3600s; ****} }

  79. Expiration 1.Vcl (beresp.ttl) 2.Cache-control s-maxage 3.Cache-control max-age 4.Expires

  80. Remove,client,cookies sub*vcl_recv*{ ****unset*req.http.cookie; } Remove,server,cookies sub*vcl_fetch*{ ****unset*beresp.http.set=cookie; }

  81. 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; ****} }

  82. Ignore,cookies sub*vcl_recv*{ ***if*(req.request*==*"GET"*||*req.request*==* "HEAD")*{ *****return*(lookup); ***} } Ignores%default%behaviour

  83. 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

  84. 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"));

    **} }
  85. ✓Purge ✓Ban ✓Always,miss Cache,invalidaWon

  86. sub*vcl_recv*{ ********if*(req.request*==*"PURGE")*{ ****************return*(lookup); ********} } sub*vcl_hit*{ ********if*(req.request*==*"PURGE")*{ ****************purge; ****************error*200*"Purged"; ********}

    } sub*vcl_miss*{ ********if*(req.request*==*"PURGE")*{ ****************error*404*"Not*in*cache"; ********} } Purge HTTP%call% to%purge
  87. ✓Implement,in,your,CMS ✓HTTP,200,:,removed,from,cache ✓HTTP,404:,not,in,cache ✓Some,CMS,plugins,require,200,for,miss() Purge curl*=X*PURGE*http://varnish.dev/your=page

  88. sub*vcl_recv*{ ********if*(req.request*==*"PURGE")*{ ban("req.http.host*==*"*+*req.http.host*+*"* &&*req.url*==*"*+*req.url); error*200*"Banned"; ********} } Ban sub*vcl_recv*{ ********if*(req.request*==*"PURGE")*{

    ************ban("req.http.host*==*"*+*req.http.host*+* "*&&*req.url*~*"*+*req.url); error*200*"Banned"; ********} } Ban%URL% pattern Ban%URL Name% doesn’t% matter
  89. sub*vcl_recv*{ ********if*(req.request*==*"PURGE")*{ ************ban("obj.http.x=host*==*"*+*req.http.host*+* "*&&*obj.http.x=url*==*"*+*req.url); ************error*200*"Banned"; ********} } sub*vcl_fetch*{ ********set*beresp.http.x=url*=*req.url; ********set*beresp.http.x=host*=*req.http.host;

    } sub*vcl_deliver*{ ********unset*resp.http.x=url; ********unset*resp.http.x=host; } Smart,bans Ban%lurker% friendly
  90. sub*vcl_recv*{ ********if*(req.request*==*"REFRESH")*{ ****************set*req.request*=*"GET"; ****************set*req.hash_always_miss*=*true; ********} } Refresh/always,miss

  91. Edge Side Includes

  92. header.php menu.php main.php footer.php TTL#5s No#caching TTL#10s TTL#2s

  93. <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>
  94. ESI#VCL sub$vcl_recv${ $$$$set$req.http.Surrogate5Capability="key=ESI/1.0"; } sub$vcl_fetch${ $ if(beresp.http.Surrogate5Control~"ESI/1.0")${ $$$$$$$$$unset$beresp.http.Surrogate5Control; $ $$$$set$beresp.do_esi=true;

    $$$$} }$
  95. None
  96. proxy_cache_path /tmp/nginx/fastcgi_cache levels=1:2 keys_zone=my-cache:10m inactive=5m; Init%cache% files%(disk,% ramdisk)

  97. location / { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_cache my-cache;

    proxy_cache_key "$scheme$request_method$host $request_uri"; proxy_cache_valid 200 302 60m; proxy_cache_valid 404 1m; }
  98. location ~ /purge(/.*) { proxy_cache_purge my-cache "$scheme $request_method$host$1";" } ✓Requires,ngx_cache_purge

    ✓Requires,separate,“purge”,URL,(buggy,behaviour) ✓https://github.com/FRiCKLE/ngx_cache_purge
  99. FPM hXp://www.php.net/manual/en/install.fpm.configura4on.php

  100. server { listen 80; root /var/www/; " location / {

    try_files $uri $uri/ /index.php; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; }" }
  101. fastcgi_cache_path /tmp/nginx/fastcgi_cache levels=1:2 keys_zone=my-cache:10m inactive=5m; Looks% familiar?

  102. location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php;

    include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_cache my-cache; fastcgi_cache_key "$scheme$request_method$host $request_uri"; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500; } FastCGI% cache%to% cache%zone
  103. location ~ /purge(/.*) { fastcgi_cache_purge my-cache "$scheme $request_method$host$1";" } Remember%

    this%one?
  104. None
  105. upstream my_memcached { " server my.memcached.org:11211; " server my.other.memcached.org:11211;" }

    upstream my_fpm { " server my.fpm.org:9000; " server my.other.fpm.org:9000;" } Upstream% servers Loadbalancing
  106. location ~ \.php$ { set $memcached_key $request_uri; memcached_pass my_memcached; memcached_next_upstream

    not_found; default_type "text/html; charset=utf-8"; error_page 404 405 502 = @php; }" location @php { default_type "text/html; charset=utf-8"; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass my_fpm; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; }
  107. <?php $contents = date("Y-m-d H:i:s"); $m = new Memcached(); $m->addServer('localhost',11211);

    $m->set($_SERVER['REQUEST_URI'], $contents,3600); echo $contents; Save%to% Memcached%&% output
  108. And# on#that# bombshell#...

  109. None
  110. Thanks