HTTP Caching and PHP

24
HTTP caching and PHP David de Boer

description

Uncon talk at Dutch PHP Conference ’14

Transcript of HTTP Caching and PHP

Page 1: HTTP Caching and PHP

HTTP caching and PHP David de Boer

Page 2: HTTP Caching and PHP

Hello DPC!

• I’m David

• Lead developer at Driebit, Amsterdam

• Open source enthusiast

Page 3: HTTP Caching and PHP

– Phil Karlton

“There are only two hard things in Computer Science: cache invalidation and naming things.”

Page 4: HTTP Caching and PHP

Why we cache

• Reduce response times

• Reduce server load

• Cheap

Page 5: HTTP Caching and PHP

How we cache

Client App

Page 6: HTTP Caching and PHP

Client AppCache

How we cache

Page 7: HTTP Caching and PHP

Efficient caching

• Maximize cache hits

• TTL ∞

Page 8: HTTP Caching and PHP

GET  /apple  HTTP/1.1Host:  fresh-­‐fruit.comConnection:  close...

!!HTTP/1.1  200  OKHost:  fresh-­‐fruit.comX-­‐Cache:  HITAge:  567648000...

Page 9: HTTP Caching and PHP

• Maximize cache hits

• TTL ∞

• Invalidation

Efficient caching

Page 10: HTTP Caching and PHP

AppCache

Let’s go invalidate

Page 11: HTTP Caching and PHP

Cache• Varnish

• Nginx

Page 12: HTTP Caching and PHP

Varnish

#  /etc/varnish/default.vcl  sub  vcl_hit  {   if  (req.request  ==  "PURGE")  {     purge;          error  204  "Purged";      } }  !sub  vcl_miss  {   if  (req.request  ==  "PURGE")  {     purge;     error  204  "Purged  (Not  in  cache)";   }}

Page 13: HTTP Caching and PHP

$  composer  require  friendsofsymfony/http-­‐cache  @alpha

FOSHttpCache

App

Page 14: HTTP Caching and PHP

Connect and purge

use  FOS\HttpCache\ProxyClient\Varnish;$servers  =  ['10.0.0.1:6081'];$proxyClient  =  new  Varnish($servers);  $proxyClient   -­‐>purge('/news/articles/42')   -­‐>purge('/news')   -­‐>flush();

Page 15: HTTP Caching and PHP

Level upsub  vcl_recv  {     if  (req.request  ==  "BAN")  {       ban("obj.http.x-­‐host  ~  "  +  req.http.x-­‐host               +  "  &&  obj.http.x-­‐url  ~  "  +  req.http.x-­‐url         +  "  &&  obj.http.content-­‐type  ~  "  +  req.http.x-­‐content-­‐type       );  !     error  200  "Banned";     }  }  !sub  vcl_fetch  {        #  Set  ban  lurker-­‐friendly  custom  headers     set  beresp.http.x-­‐url  =  req.url;        set  beresp.http.x-­‐host  =  req.http.host;  }

Page 16: HTTP Caching and PHP

Level up

use  FOS\HttpCache\CacheInvalidator;  !$invalidator  =  new  CacheInvalidator(    $proxyClient);  !$invalidator    -­‐>invalidateRegex('.*',  'image/png')    -­‐>invalidateRegex('^/admin')   -­‐>flush();

Page 17: HTTP Caching and PHP

Get organized

• Complex relationships between URLs

• Knowing when to invalidate what

• Depends on application logic

Page 18: HTTP Caching and PHP

Taggingsub  vcl_recv  {     if  (req.request  ==  "BAN")  {       if  (req.http.x-­‐cache-­‐tags)  {       ban("obj.http.x-­‐host  ~  "  +  req.http.x-­‐host           +  "  &&  obj.http.x-­‐url  ~  "  +  req.http.x-­‐url                      +  "  &&  obj.http.content-­‐type  ~  "    +  req.http.x-­‐content-­‐type                      +  "  &&  obj.http.x-­‐cache-­‐tags  ~  "    +  req.http.x-­‐cache-­‐tags         );         error  200  "Banned";       }  else  {         #  ...       }     }  }  !#  ...

Page 19: HTTP Caching and PHP

Tagging

//  overview.phpheader('Cache-­‐Control:  max-­‐age=3600');header('X-­‐Cache-­‐Tags:  art-­‐1,art-­‐2,art-­‐3');  !!//  article.phpheader('Cache-­‐Control:  max-­‐age=3600');header('X-­‐Cache-­‐Tags:  art-­‐2');  $invalidator-­‐>invalidateTags(['art-­‐2']);

Page 20: HTTP Caching and PHP

use  FOS\HttpCache\Tests\VarnishTestCase;  !class  MyTest  extends  VarnishTestCase{   public  function  testHit()   {       $first  =  $this-­‐>getResponse('/cached.php');       $this-­‐>assertMiss($first);       $second  =  $this-­‐>getResponse('/cached.php');       $this-­‐>assertHit($second);    }}

OK  (1  test,  2  assertions)

Test-driven invalidation

Page 21: HTTP Caching and PHP

Test-driven invalidation

class  MyTest  extends  VarnishTestCase{   public  function  testTags()   {     $miss  =  $this-­‐>getResponse('/article.php');          $hit  =  $this-­‐>getResponse('/article.php');            $invalidator-­‐>invalidateTags(['art-­‐2']);          $this-­‐>assertMiss($this-­‐>getResponse('/article.php'));      } }

OK  (1  test,  1  assertion)

Page 22: HTTP Caching and PHP

Symfony bundle$  composer  require  friendsofsymfony/http-­‐cache-­‐bundle  @alpha  !/**  *  @InvalidateRoute("fruits-­‐overview",  params={"type"  =  "latest"})    *  @InvalidateRoute("fruits",  params={"num"  =  "id"})    */public  function  editAction($id){     #  ... /**  *  @Tag(expression="'fruit-­‐'~$id")  */public  function  showAction($id){     #  ...

Page 23: HTTP Caching and PHP

Symfony bundlefos_http_cache:     cache_control:       rules:         -­‐           match:                           host:  ^login.example.com$           headers:             cache_control:               public:  false               s_maxage:  0               last_modified:  "-­‐1  hour"             vary:  [Accept-­‐Encoding,  Accept-­‐Language]         -­‐           match:             attributes:  {  _controller:  ^AcmeBundle:Default:.*  }             additional_cacheable_status:  [400]           headers:             cache_control:  {  public:  true,  max_age:  15,  s_maxage:  30  }  

Page 24: HTTP Caching and PHP

[email protected]

https://github.com/FriendsOfSymfony/FOSHttpCache

https://github.com/FriendsOfSymfony/FOSHttpCacheBundle

http://foshttpcache.readthedocs.org