Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

Slides for my C.R.E.A.M. (Cache Rules Everything Around Me) talk at Loadays 2013. #loadays #load13

Thijs Feryn

April 06, 2013
Tweet

More Decks by Thijs Feryn

Other Decks in Technology

Transcript

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

    View full-size slide

  2. Hi#
    my#name#
    is#Thijs

    View full-size slide

  3. I’m#
    an#evangelist#at

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  6. Old school
    Store/cache
    to avoid
    recalculation

    View full-size slide

  7. Protect your
    infrastructure

    View full-size slide

  8. Responsibilities

    View full-size slide

  9. Tear down silos

    View full-size slide

  10. Fundamentals

    View full-size slide

  11. Browser#cache
    Page#cache
    Internal#data#cache
    Opcode#cache

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. Lexing
    Source,
    to,tokens
    Tokenizing
    Interpre4ng,
    tokens
    Compiling
    Generate,
    byte,code
    Execu4on
    Run,
    byte,code

    View full-size slide

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

    View full-size slide

  17. Zend#Optimizer#(plus)
    Ioncube
    Eaccelerator
    XCache
    APC

    View full-size slide

  18. Which direction
    are we heading?

    View full-size slide

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

    View full-size slide

  20. Caching internal data

    View full-size slide

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

    View full-size slide

  22. Memcached
    ✓Key value store
    ✓Distributed cache
    ✓Over TCP/IP
    ✓Stored in memory
    ✓Fast
    ✓Client-side intelligence

    View full-size slide

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

    View full-size slide

  24. $m = new Memcached();
    $m->addServer('localhost',11211);
    $value1 = $m->get('key1');
    $result = $m->getMulti(array('key2','key3','key4'));
    var_dump($value1,$result);
    Retrieve

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  27. $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 "$i not in cache, setting to $value
    >".PHP_EOL;
    echo "Error: ".$m->getResultMessage()." (".$m->getResultCode().")>".PHP_EOL;
    } else {
    echo "Value for $i: $value
    ".PHP_EOL;
    }
    }
    High availability

    View full-size slide

  28. Memcached
    memcached.sess_prefix = "memc.sess.key."
    session.save_path="127.0.0.1:11211"
    session.save_handler = memcached
    Also%
    for%session%
    handling

    View full-size slide

  29. ✓Just like Memcached
    ✓Replication
    ✓Disk persistence
    ✓Data structures
    ✓Transactions
    ✓More partitioning options
    ✓PubSub

    View full-size slide

  30. Keys
    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')
    );

    View full-size slide

  31. Strings
    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')
    );

    View full-size slide

  32. Hashes
    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')
    );

    View full-size slide

  33. Lists
    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)
    );

    View full-size slide

  34. Sets
    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')
    );

    View full-size slide

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

    View full-size slide

  36. APC
    User%
    func*ons

    View full-size slide

  37. 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')
    );

    View full-size slide

  38. 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)
    }
    }
    }
    }

    View full-size slide

  39. Page caching

    View full-size slide

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

    View full-size slide

  41. ! location / {
    try_files $uri $uri/ /index.php;
    }
    Nginx

    View full-size slide

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

    View full-size slide

  43. [PHP]
    auto_prepend_file*“/path/to/prepend.php”
    auto_append_file*“/path/to/append.php”
    Auto#
    execute#before#
    after#each#
    script

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  46. File
    MySQL
    APC
    Memcached
    Redis

    View full-size slide

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

    View full-size slide

  48. Avoid#
    PHP#runtime#
    entirely

    View full-size slide

  49. Reverse proxy

    View full-size slide

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

    View full-size slide

  51. Out of the box

    View full-size slide

  52. Only get & HEAD
    No cookie & auth headers
    No set-cookie headers
    cache ttl > 0
    No vary “*”
    When will varnish cache?

    View full-size slide

  53. Request vcl_recv
    In cache?
    vcl_hash Cacheable?
    vcl_hit() vcl_miss()
    vcl_deliver()
    vcl_fetch()
    No
    Yes
    No
    Yes
    Response

    View full-size slide

  54. 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);
    }

    View full-size slide

  55. 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);
    }

    View full-size slide

  56. 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);
    }

    View full-size slide

  57. sub vcl_error {
    set obj.http.Content-Type = "text/html; charset=utf-8";
    set obj.http.Retry-After = "5";
    synthetic {"

    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">


    "} + obj.status + " " + obj.response + {"


    Error "} + obj.status + " " + obj.response + {"
    "} + obj.response + {"
    Guru Meditation:
    XID: "} + req.xid + {"

    Varnish cache server


    "};
    return (deliver);
    }
    sub vcl_init {
    " return (ok);
    }
    sub vcl_fini {
    " return (ok);
    }

    View full-size slide

  58. Monitoring
    &
    Logging

    View full-size slide

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

    View full-size slide

  60. ...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,

    View full-size slide

  61. ...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,

    View full-size slide

  62. ...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,

    View full-size slide

  63. varnishlog -c -m VCL_call:hit | grep -i 'RxURL'
    Varnishlog
    varnishlog -b -i TxURL
    Hits Misses

    View full-size slide

  64. Cache,staTc,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);
    ..}
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  69. 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;
    ....}
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide


  73. Purge

    Ban

    Always,miss
    Cache,invalidaTon

    View full-size slide

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

    View full-size slide

  75. ✓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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  78. sub.vcl_recv.{
    ........if.(req.request.==."REFRESH").{
    ................set.req.request.=."GET";
    ................set.req.hash_always_miss.=.true;
    ........}
    }
    Refresh/always,miss

    View full-size slide

  79. Edge Side Includes

    View full-size slide

  80. header.php
    menu.php main.php
    footer.php
    TTL,5s
    No,caching
    TTL,10s
    TTL,2s

    View full-size slide

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

    View full-size slide

  82. proxy_cache_path /tmp/nginx/fastcgi_cache
    levels=1:2 keys_zone=my-cache:10m inactive=5m;
    Init,cache,
    files,(disk,,
    ramdisk)

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  85. FPM
    hCp://www.php.net/manual/en/install.fpm.configuraHon.php

    View full-size slide

  86. 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;
    }!
    }

    View full-size slide

  87. fastcgi_cache_path /tmp/nginx/fastcgi_cache
    levels=1:2 keys_zone=my-cache:10m inactive=5m;
    Looks,
    familiar?

    View full-size slide

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

    View full-size slide

  89. location ~ /purge(/.*) {
    fastcgi_cache_purge my-cache "$scheme
    $request_method$host$1";"
    }
    Remember,
    this,one?

    View full-size slide

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

    View full-size slide

  91. 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;
    }

    View full-size slide

  92. $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

    View full-size slide

  93. And#
    on#that#
    bombshell#...

    View full-size slide