Caching on the Edge

17,562 views
16,972 views

Published on

Published in: Technology
1 Comment
48 Likes
Statistics
Notes
No Downloads
Views
Total views
17,562
On SlideShare
0
From Embeds
0
Number of Embeds
848
Actions
Shares
0
Downloads
362
Comments
1
Likes
48
Embeds 0
No embeds

No notes for slide

Caching on the Edge

  1. 1. Speaker | Company Title // Presentation Name Caching on the Edge Fabien Potencier
  2. 2. Who are you?
  3. 3. May 1996 RFC1945 – HTTP/1.0
  4. 4. March 1999 RFC2616 – HTTP/1.1 http://www.ietf.org/rfc/rfc2616.txt
  5. 5. HTTP Bis –Work in progress http://tools.ietf.org/wg/httpbis/ http://www.flickr.com/photos/visualpanic/233508614
  6. 6.  p1: Messaging: Low-level message parsing and connection management  p2: Semantics: Methods, status codes and headers  p3: Payload: Dealing with content, message-specific headers  p4: Conditional Requests: e.g., If-Modified-Since  p5: Range Requests: Getting partial content  p6: Caching: Browser and intermediary caches  p7: Authentication: HTTP authentication framework
  7. 7. HTTP
  8. 8. The Client sends a Request to the Server The Server sends back a Response to the Client A Client (browser, bot,WS, curl, …) A Server (Apache, nginx, …) The Request and the Response are HTTP messages
  9. 9. Let’s play with HTTP and HTTP headers
  10. 10. GET / HTTP/1.1 Host: http.trainings.sensiolabs.com
  11. 11. « The request-header fields allow the client to pass additional information about the request, and about the client itself, to the server.These fields act as request modifiers, with semantics equivalent to the parameters on a programming language method invocation. »
  12. 12. « Each HTTP header field consists of a case-insensitive field name followed by a colon (":"), optional whitespace, and the field value »
  13. 13. HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Server: Apache Content-Length: 14 Content-Type: text/html Hello World!
  14. 14. Live HTTP headers Firefox extension http://livehttpheaders.mozdev.org/
  15. 15. $ curl -i http://http.trainings.sensiolabs.com/ HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Server: Apache Content-Length: 14 Content-Type: text/html Hello World!
  16. 16. $ telnet localhost 80 Trying ::1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.1 Host: http.trainings.sensiolabs.com HTTP/1.1 200 OK Date: Wed, 15 Oct 2005 07:07:07 GMT Server: Apache Content-Length: 14 Content-Type: text/html Hello World! Connection closed by foreign host.
  17. 17. HTTP Headers with PHP
  18. 18. header('Content-Type: text/plain'); header('content-type: text/plain');
  19. 19. Caching in the HTTP Specification
  20. 20.  p1: Messaging: Low-level message parsing and connection management  p2: Semantics: Methods, status codes and headers  p3: Payload: Dealing with content, message-specific headers  p4: Conditional Requests: e.g., If-Modified-Since  p5: Range Requests: Getting partial content  p6: Caching: Browser and intermediary caches  p7: Authentication: HTTP authentication framework
  21. 21. HTTP Expiration HTTPValidation Fresh vs Stale
  22. 22. HTTP Headers for Expiration Cache-Control Expires
  23. 23. HTTP Headers forValidation Last-Modified / If-Modified-Since ETag / If-None-Match
  24. 24. HTTP Cache headers only work with“safe”HTTP methods (like GET & HEAD)
  25. 25. Never change the state of the server when serving a GET request (we are talking about the application’s state of course, you can log, cache, …)
  26. 26. HTTP Expiration
  27. 27. Expires « The "Expires" header field gives the date/time after which the response is considered stale. »
  28. 28. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org HTTP/1.1 200 OK Expires: Thu,  01  Dec  …   Hello GET /foo HTTP/1.1 200 OK Expires: Thu,  01  Dec   …   Hello HTTP/1.1 200 OK Expires: Thu,  01  Dec  …   Hello
  29. 29. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK Expires: Thu,  01  Dec   …   Hello HTTP/1.1 200 OK Expires: Thu,  01  Dec  …   Hello Before  expira4on   Your  applica4on  is  not  called  
  30. 30. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org HTTP/1.1 200 OK Expires: Thu,  01  Dec  …   Hello GET /foo HTTP/1.1 200 OK Expires: Thu,  01  Dec   …   Hello HTTP/1.1 200 OK Expires: Thu,  01  Dec  …   Hello A<er  expira4on   Not  fresh  
  31. 31. Expires: Thu, 01 Dec 2010 16:00:00 GMT Date in RFC1123 format, not RFC2822 (timezone always GMT, which is ~ UTC)
  32. 32. $expires = gmdate('D, j M Y H:i:s T', time() + 5); header('Expires: '.$expires);
  33. 33. $date = new DateTime(null, new DateTimeZone('UTC')); $date->modify('+5 seconds'); $expires = $date->format('D, d M Y H:i:s').' GMT'; $date = gmdate('D, j M Y H:i:s T', time() + 5); header('Expires: '.$expires);
  34. 34. $date->setTimezone(new DateTimeZone('UTC'));
  35. 35. /expires_with_expires_in_5s.php
  36. 36. WARNING The clocks on theWeb server AND the cache (aka browser) MUST be synchronised
  37. 37. WARNING « HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future. »
  38. 38. Mostly useful to make static assets (images, css, js, …) cacheable with an extremely long expiry time But there is a better way!
  39. 39. Use Cache-Control instead
  40. 40. header('Cache-Control: max-age=5');
  41. 41. http.trainings.sensiolabs.com/expires_in_5s.php
  42. 42. Don’t use Expires Use Cache-Control …except if you want to set a date, which should be pretty rare
  43. 43. HTTPValidation
  44. 44. “304 Not Modified”is your friend
  45. 45. HTTP Headers forValidation Etag / If-None-Match
  46. 46. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK ETag: abcdef   …   Hello HTTP/1.1 200 OK ETag: abcdef   Hello HTTP/1.1 200 OK ETag: abcdef   Hello
  47. 47. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-None-Match: abcdef HTTP/1.1 304 Not Modified GET /foo HTTP/1.1 200 OK ETag: abcdef   …   Hello HTTP/1.1 200 OK ETag: abcdef   Hello If  the  resource  has  not  changed  
  48. 48. SomeCache GET /foo HTTP/1.1 200 OK ETag: abcdef   …   Hello Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-None-Match: abcdef If  the  resource  has  changed   GET /foo HTTP/1.1 200 OK ETag: 123456   …   Hello HTTP/1.1 200 OK ETag: 123456   Hello HTTP/1.1 200 OK ETag: 123456   Hello
  49. 49. // compute ETag value $etag = '...'; if ( isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag ) { header('HTTP/1.1 304 Not Modified'); } else { header('ETag: '.$etag); echo 'Hello'; }
  50. 50. This is a simple but naïve implementation…
  51. 51. HTTP Headers forValidation Last-Modified / If-Modified-Since
  52. 52. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK Last-Modified: Thu,     …   Hello HTTP/1.1 200 OK Last-Modified: Thu,  …   Hello HTTP/1.1 200 OK Last-Modified: Thu,  …   Hello
  53. 53. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-Modified-Since: Thu, HTTP/1.1 304 Not Modified GET /foo HTTP/1.1 200 OK Last-Modified: Thu,     …   Hello HTTP/1.1 200 OK Last-Modified: Thu,  …   Hello If  the  resource  has  not  changed  
  54. 54. SomeCache GET /foo HTTP/1.1 200 OK Last-Modified: Thu, …   Hello GET /foo HTTP/1.1 200 OK Last-Modified: Sun, …   Hello Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-Modified-Since: Thu, If  the  resource  has  changed   HTTP/1.1 200 OK Last-Modified: Sun,  …   Hello HTTP/1.1 200 OK Last-Modified: Sun,  …   Hello
  55. 55. Expiration &Validation
  56. 56. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK Etag: abcdef Cache-­‐Control:  max-­‐ age=10   …   Hello HTTP/1.1 200 OK ETag: abcdef   Cache-­‐Control:  max-­‐age=10   Hello HTTP/1.1 200 OK ETag: abcdef   Cache-­‐Control:  max-­‐age=10   Hello
  57. 57. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org Before  expira4on   Your  applica4on  is  not  called   GET /foo HTTP/1.1 200 OK Etag: abcdef Cache-­‐Control:  max-­‐ age=10   …   Hello HTTP/1.1 200 OK ETag: abcdef   Cache-­‐Control:  max-­‐age=10   Hello
  58. 58. Browser YourPHPapplication SomeCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-None-Match: abcdef HTTP/1.1 304 Not Modified Cache-­‐Control:  max-­‐age=10   A<er  expira4on   but  resource  s4ll  valid   GET /foo HTTP/1.1 200 OK Etag: abcdef Cache-­‐Control:  max-­‐ age=10   …   Hello HTTP/1.1 200 OK ETag: abcdef   Cache-­‐Control:  max-­‐age=10   Hello
  59. 59. You can combine HTTP headers the way you want Expiration wins overValidation
  60. 60. Expiration allows you to scale as less requests hit your server (and client speed is better too) Validation saves bandwidth
  61. 61. The goal is to never generate the same response twice
  62. 62. PHP and Cache HTTP headers
  63. 63. session_start(); $_SESSION['foo'] = 'bar'; echo 'Hello';
  64. 64. http.trainings.sensiolabs.com/index.php http.trainings.sensiolabs.com/cookie.php
  65. 65. Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
  66. 66. Kinds of caches
  67. 67. Browser Cache
  68. 68. On  the  server  side   Browser YourPHPapplication BrowserCache
  69. 69. Within  a  Company   On  the  server  side   Browser YourPHPapplication BrowserBrowser BrowserCacheBrowserCacheBrowserCache
  70. 70. Proxy Cache
  71. 71. On  the  server  side   Within  a  Company   Browser YourPHPapplication BrowserBrowser BrowserCacheBrowserCacheBrowserCache ProxyCache
  72. 72. On  the  server  side   Within  a  Company   Browser YourPHPapplication BrowserBrowser BrowserCacheBrowserCacheBrowserCache ProxyCache Within  a  Company   BrowserBrowserBrowser BrowserCacheBrowserCacheBrowserCache ProxyCache
  73. 73. Gateway Cache
  74. 74. On  the  server  side   YourPHPapplication Browser BrowserCache GatewayCache
  75. 75. Within  a  Company   On  the  server  side   Browser YourPHPapplication BrowserBrowser BrowserCacheBrowserCacheBrowserCache GatewayCache
  76. 76. On  the  server  side   Within  a  Company   Browser YourPHPapplication BrowserBrowser BrowserCacheBrowserCacheBrowserCache ProxyCache BrowserBrowser BrowserCacheBrowserCache GatewayCache
  77. 77. Your PHP application Gateway Cache Reverse Proxy Cache Surrogate Cache HTTP Accelerator Browser Browser Cache Proxy Cache
  78. 78. Browser Cache Local cache for when you hit“back”or when images are reused throughout a website
  79. 79. Proxy Cache A shared cache Many people behind a single proxy Installed by large corporations and ISPs Reduce latency and network traffic
  80. 80. Gateway Cache A shared cache on the server side Installed by network administrators Make websites more scalable, reliable and performing better CDNs like Akaïma are gateway caches
  81. 81. Today, we will mainly talk about Gateway caches
  82. 82. Edge Caching
  83. 83. App Browser Browser Gateway Cache Gateway Cache
  84. 84. HTTP 1.1 allows caching anything by default unless explicit Cache-Control header
  85. 85. In practice, most caches avoid anything with Cache-Control Cookie / Set-Cookie WWW-Authenticate / Authorization POST / PUT 302 / 307 status codes
  86. 86. Cache-Control: private This is the default with PHP when you have a session Browser cache will still work fine here (public means shared caches, private means browser cache)
  87. 87. A gateway cache won't cache anything "private" or carrying a cookie In a real-world: tracking cookies (Google Analytics)
  88. 88. All proxies do caching based on the same HTTP headers
  89. 89. We need several clients to understand how it works and how the cached is shared
  90. 90. HTTP Expiration
  91. 91. GatewayCache Bob YourPHPapplication Bob’sCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK C-C: max-age=600   …   Hello HTTP/1.1 200 OK C-C: max-age=600   Hello HTTP/1.1 200 OK C-C: max-age=600   Hello GET /foo HTTP/1.1 200 OK C-C: max-age=600   …   Hello HTTP/1.1 200 OK C-C: max-age=600   Hello
  92. 92. Bob’sCache GatewayCache Bob YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK C-C: max-age=600   …   Hello HTTP/1.1 200 OK C-C: max-age=600   Hello GET /foo HTTP/1.1 200 OK C-C: max-age=600   …   Hello
  93. 93. BrowserCache Alice YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org HTTP/1.1 200 OK C-C: max-age=600   Hello HTTP/1.1 200 OK C-C: max-age=600   Hello GatewayCache GET /foo HTTP/1.1 200 OK C-C: max-age=600   …   Hello GET /foo HTTP/1.1 200 OK C-C: max-age=600   …   Hello
  94. 94. HTTPValidation
  95. 95. Bob’sCache GatewayCache Bob YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 200 OK Etag: abcde   …   Hello HTTP/1.1 200 OK Etag: abcde   Hello HTTP/1.1 200 OK Etag: abcde   Hello GET /foo HTTP/1.1 200 OK Etag: abcde   …   Hello HTTP/1.1 200 OK Etag: abcde   Hello
  96. 96. Bob’sCache GatewayCache Bob YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-None-Match: ab GET /foo HTTP/1.1 Host: foo.org If-None-Match: ab GET /foo HTTP/1.1 200 OK Etag: ab   …   Hello HTTP/1.1 200 OK Etag: ab   Hello GET /foo HTTP/1.1 200 OK Etag: ab   …   Hello 304 Not Modified304 Not Modified
  97. 97. GatewayCache YourPHPapplication BrowserCache GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org If-None-Match: ab GET /foo HTTP/1.1 200 OK Etag: ab   …   Hello HTTP/1.1 200 OK Etag: ab   Hello 304 Not Modified Alice HTTP/1.1 200 OK Etag: ab   Hello GET /foo HTTP/1.1 200 OK Etag: ab   …   Hello
  98. 98. Gateway caches Varnish (only does that and tries to do it well) Squid (just one way to use it) mod_cache (Apache)
  99. 99. Gateway caches are a great way to make your website performs better
  100. 100. But what if you cannot cache whole pages? What if a page has "more" dynamic parts?
  101. 101. Lorem  ipsum  dolor  sit   amet,  consectetur   adipiscing  elit.  In  vel  nulla   arcu,  vitae  cursus  nunc.   Integer  semper  turpis  et   enim  porRtor  iaculis.   Nulla  facilisi.  Lorem  ipsum   dolor  sit  amet,   consectetur  adipiscing  elit.   Mauris  vehicula   ves4bulum  dictum.   Aenean  non  velit  tortor.   Nullam  adipiscing   malesuada  aliquam.   Mauris  dignissim,  urna   quis  iaculis  tempus,  justo   libero  porRtor  est,  nec   eleifend  est  elit  vitae  ante.   Curabitur  interdum  luctus   metus.   Lorem  ipsum  dolor  sit  amet,  consectetur   adipiscing  elit.  In  vel  nulla  arcu,  vitae   cursus  nunc.  Integer  semper  turpis  et  enim   porRtor  iaculis.  Nulla  facilisi.  Lorem  ipsum   dolor  sit  amet,  consectetur  adipiscing  elit.   Mauris  vehicula  ves4bulum  dictum.   Aenean  non  velit  tortor.  Nullam  adipiscing   malesuada  aliquam.  Mauris  dignissim,  urna   quis  iaculis  tempus,  justo  libero  porRtor   est,  nec  eleifend  est  elit  vitae  ante.   Curabitur  interdum  luctus  metus,  in   pulvinar  lectus  rutrum  sit  amet.  Duis   gravida,  metus  in  dictum  eleifend,  dolor   risus  4ncidunt  ligula,  non  volutpat  nulla   sapien  in  elit.  Nulla  rutrum  erat  id  neque   suscipit  eu  ultricies  odio  sollicitudin.   Aliquam  a  mi  vel  eros  placerat  hendrerit.   Phasellus  porRtor,  augue  sit  amet   vulputate  venena4s,  dui  leo  commodo   odio,  a  euismod  turpis  ligula  in  elit.     cacheable for 10 seconds cacheable for 5 seconds
  102. 102. ESI… or Edge Side Includes http://www.w3.org/TR/esi-lang
  103. 103. Lorem  ipsum  dolor  sit   amet,  consectetur   adipiscing  elit.  In  vel  nulla   arcu,  vitae  cursus  nunc.   Integer  semper  turpis  et   enim  porRtor  iaculis.   Nulla  facilisi.  Lorem  ipsum   dolor  sit  amet,   consectetur  adipiscing  elit.   Mauris  vehicula   ves4bulum  dictum.   Aenean  non  velit  tortor.   Nullam  adipiscing   malesuada  aliquam.   Mauris  dignissim,  urna   quis  iaculis  tempus,  justo   libero  porRtor  est,  nec   eleifend  est  elit  vitae  ante.   Curabitur  interdum  luctus   metus.   Lorem  ipsum  dolor  sit  amet,  consectetur   adipiscing  elit.  In  vel  nulla  arcu,  vitae   cursus  nunc.  Integer  semper  turpis  et  enim   porRtor  iaculis.  Nulla  facilisi.  Lorem  ipsum   dolor  sit  amet,  consectetur  adipiscing  elit.   Mauris  vehicula  ves4bulum  dictum.   Aenean  non  velit  tortor.  Nullam  adipiscing   malesuada  aliquam.  Mauris  dignissim,  urna   quis  iaculis  tempus,  justo  libero  porRtor   est,  nec  eleifend  est  elit  vitae  ante.   Curabitur  interdum  luctus  metus,  in   pulvinar  lectus  rutrum  sit  amet.  Duis   gravida,  metus  in  dictum  eleifend,  dolor   risus  4ncidunt  ligula,  non  volutpat  nulla   sapien  in  elit.  Nulla  rutrum  erat  id  neque   suscipit  eu  ultricies  odio  sollicitudin.   Aliquam  a  mi  vel  eros  placerat  hendrerit.   Phasellus  porRtor,  augue  sit  amet   vulputate  venena4s,  dui  leo  commodo   odio,  a  euismod  turpis  ligula  in  elit.    
  104. 104. Lorem  ipsum  dolor  sit  amet,  consectetur   adipiscing  elit.  In  vel  nulla  arcu,  vitae   cursus  nunc.  Integer  semper  turpis  et  enim   porRtor  iaculis.  Nulla  facilisi.  Lorem  ipsum   dolor  sit  amet,  consectetur  adipiscing  elit.   Mauris  vehicula  ves4bulum  dictum.   Aenean  non  velit  tortor.  Nullam  adipiscing   malesuada  aliquam.  Mauris  dignissim,  urna   quis  iaculis  tempus,  justo  libero  porRtor   est,  nec  eleifend  est  elit  vitae  ante.   Curabitur  interdum  luctus  metus,  in   pulvinar  lectus  rutrum  sit  amet.  Duis   gravida,  metus  in  dictum  eleifend,  dolor   risus  4ncidunt  ligula,  non  volutpat  nulla   sapien  in  elit.  Nulla  rutrum  erat  id  neque   suscipit  eu  ultricies  odio  sollicitudin.   Aliquam  a  mi  vel  eros  placerat  hendrerit.   Phasellus  porRtor,  augue  sit  amet   vulputate  venena4s,  dui  leo  commodo   odio,  a  euismod  turpis  ligula  in  elit.     <esi:include src="..." />
  105. 105. <esi:include src="http://..." />
  106. 106. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /bar HTTP/1.1 Host: foo.org Lorem   ipsum   dolor     <esi:include   src="hYp.."  />   HTTP/1.1 200 OK Lorem  ipsum   dolor   HTTP/1.1 200 OK Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK
  107. 107. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /bar HTTP/1.1 Host: foo.org Lorem   ipsum   dolor     <esi:include   src="hYp.."  />   HTTP/1.1 200 OK C-C: max-age=10 Lorem  ipsum   dolor   HTTP/1.1 200 OK C-C: max-age=5 Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK GET /foo C-C: max-age=10   Lor <esi:include /> GET /bar C-C: max-age=5   Lorem GET /foo C-C: max-age=10   Lor Lorem
  108. 108. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK GET /foo C-C: max-age=10   Lor <esi:include /> GET /bar C-C: max-age=5   Lorem GET /foo C-C: max-age=10   Lor Lorem 2  seconds  later…  
  109. 109. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK GET /foo C-C: max-age=10   Lor <esi:include /> GET /bar C-C: max-age=5   Lorem GET /foo C-C: max-age=10   Lor Lorem 7  seconds  later…   WRONG  
  110. 110. Cache-Control: max-age=10 Cache-Control: s-maxage=10
  111. 111. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /bar HTTP/1.1 Host: foo.org Lorem   ipsum   dolor     <esi:include   src="hYp.."  />   HTTP/1.1 200 OK C-C: s-maxage=10 Lorem  ipsum   dolor   HTTP/1.1 200 OK C-C: s-maxage=5 Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK GET /foo C-C: s-maxage=10   Lor <esi:include /> GET /bar C-C: s-maxage=5   Lorem
  112. 112. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK GET /foo C-C: s-maxage=10   Lor <esi:include /> GET /bar C-C: s-maxage=5   Lorem 2  seconds  later…  
  113. 113. BrowserCache GatewayCache Browser YourPHPapplication GET /foo HTTP/1.1 Host: foo.org GET /foo HTTP/1.1 Host: foo.org GET /bar HTTP/1.1 Host: foo.org Lorem  ipsum   dolor   HTTP/1.1 200 OK C-C: s-maxage=5 Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK Lorem  ipsum   dolor  sit   amet,     Lorem   ipsum   dolor   HTTP/1.1 200 OK GET /foo C-C: s-maxage=10   Lor <esi:include /> GET /bar C-C: s-maxage=5   Lorem 7  seconds  later…  
  114. 114. Lorem  ipsum  dolor  sit   amet,  consectetur   adipiscing  elit.  In  vel  nulla   arcu,  vitae  cursus  nunc.   Integer  semper  turpis  et   enim  porRtor  iaculis.   Nulla  facilisi.  Lorem  ipsum   dolor  sit  amet,   consectetur  adipiscing  elit.   Mauris  vehicula   ves4bulum  dictum.   Aenean  non  velit  tortor.   Nullam  adipiscing   malesuada  aliquam.   Mauris  dignissim,  urna   quis  iaculis  tempus,  justo   libero  porRtor  est,  nec   eleifend  est  elit  vitae  ante.   Curabitur  interdum  luctus   metus.   Lorem  ipsum  dolor  sit  amet,   consectetur  adipiscing  elit.  In  vel  nulla   arcu,  vitae  cursus  nunc.  Integer  semper   turpis  et  enim  porRtor  iaculis.  Nulla   facilisi.  Lorem  ipsum  dolor  sit  amet,   consectetur  adipiscing  elit.  Mauris   vehicula  ves4bulum  dictum.  Aenean   non  velit  tortor.  Nullam  adipiscing   malesuada  aliquam.  Mauris  dignissim,   urna  quis  iaculis  tempus,  justo  libero   porRtor  est,  nec  eleifend  est  elit  vitae   ante.  Curabitur  interdum  luctus  metus,   in  pulvinar  lectus  rutrum  sit  amet.  Duis   gravida,  metus  in  dictum  eleifend,   dolor  risus  4ncidunt  ligula,  non   volutpat  nulla  sapien  in  elit.  Nulla   rutrum  erat  id  neque  suscipit  eu   ultricies  odio  sollicitudin.  Aliquam  a  mi   vel  eros  placerat  hendrerit.  Phasellus   porRtor,  augue  sit  amet  vulputate   venena4s,  dui  leo  commodo  odio,  a   euismod  turpis  ligula  in  elit.     Lorem  ipsum  dolor  sit   amet,  consectetur   adipiscing  elit.  In  vel   nulla  arcu,  vitae  cursus   nunc.  Integer  semper   turpis  et  enim  porRtor   iaculis.  Nulla  facilisi.   Lorem  ipsum  dolor  sit   amet,  consectetur   adipiscing  elit.  Mauris   vehicula  ves4bulum   dictum.  Aenean  non   velit  tortor.  Nullam   adipiscing  malesuada   aliquam.     Lorem  ipsum  dolor  sit   amet,  consectetur   adipiscing  elit.  In  vel   nulla  arcu,  vitae   cursus  nunc.     main template layout base layout included page included page included page
  115. 115. sub vcl_fetch { esi; }
  116. 116. varnishlog -i TxURL varnishlog –o VCL_call hit | grep RxURL
  117. 117. Make your application work when ESI is enabled and when it’s not And only parse for ESIs when it’s needed
  118. 118. Surrogate-Capability Surrogate-Control http://www.w3.org/TR/edge-arch
  119. 119. Surrogate-Capability: abc="Surrogate/1.0 ESI/1.0"
  120. 120. Surrogate-Control: content="ESI/1.0"
  121. 121. RewriteEngine On RewriteRule ^(.*)$ index.php [QSA,L]
  122. 122. sub vcl_recv { set req.http.Surrogate-Capability = "abc=ESI/1.0"; } sub vcl_fetch { if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; esi; } }
  123. 123. function has_surrogate_ESI_capability() { return isset($_SERVER['HTTP_SURROGATE_CAPABILITY']) && preg_match('#ESI/1.0#', $_SERVER['HTTP_SURROGATE_CAPABILITY']); }
  124. 124. function add_surrogate_control() { header('Surrogate-Control: content="ESI/1.0"'); }
  125. 125. function include($path) { if (has_surrogate_ESI_capability()) { $path = get_absolute_path($path); echo '<esi:include src="'.$path.'" />'; add_surrogate_control(); } else { include dirname(__FILE__).'/'.$path; } }
  126. 126. Imagine the power when you combine ESI, expiration, validation, max-age, s-maxage, …
  127. 127. Why would you want to reinvent the wheel? and implement your own caching system?
  128. 128. Because you cannot afford to useVarnish? Because you use a shared hosting company?
  129. 129. <?php // With the Symfony2 HTTP accelerator instead of Varnish // won't work if you use exit() for instance... // won't work if you have "global" state // This is just a skeleton to get you started // Of course, this is native with Symfony2 ;)
  130. 130. use SymfonyComponentHttpFoundationResponse; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelHttpKernelInterface; use SymfonyComponentHttpKernelCacheCache; use SymfonyComponentHttpKernelCacheEsi; use SymfonyComponentHttpKernelCacheStore; class AppKernel implements HttpKernelInterface { public function handle(Request $request = null, $type = HttpKernelInterface::MASTER_REQUEST, $raw = false) { return new Response($content, 200, $headers); } public function getRequest() {} }
  131. 131. $_SERVER['HTTP_SURROGATE_CAPABILITY'] = 'symfony2="ESI/1.0"'; // quick hack... not secure at all! $base = str_replace('index.php', '', $request->getScriptName()); $script = str_replace($base, '', $request->getRequestUri()); ob_start(); include __DIR__.'/'.$script; $content = ob_get_clean(); $headers = array(); foreach (headers_list() as $header) { $elements = explode(':', $header, 2); $headers[$elements[0]] = trim($elements[1]); } // do not deal with response others than 200 // implementation depends on your code return new Response($content, 200, $headers);
  132. 132. $kernel = new AppKernel(); $store = new Store('/path/to/http_cache'); $esi = new Esi(); $cache = new Cache($kernel, $store, $esi); $cache->handle()->send(); error_log($cache->getLog());
  133. 133. Goal Be as dynamic as needed Hit the application as less as possible
  134. 134. The power is even bigger than what you think…
  135. 135. <esi:include src="http://...” alt="http://...” onerror="continue" />
  136. 136. stale-while-revalidate - rfc5861
  137. 137. stale-if-error - rfc5861
  138. 138. ThereareonlytwohardthingsinComputerScience: cacheinvalidationandnamingthings. --PhilKarlton http://martinfowler.com/bliki/TwoHardThings.html
  139. 139. PURGE: varnishadm -T localhost:6082 purgeurl "^/images/ »
  140. 140. acl purge_acl { "localhost"; "1.2.3.4"; } sub vcl_recv { if (req.request == "PURGE") { if (!client.ip ~ purge_acl) { error 405 "Not allowed."; } purge_url(req.url); error 200 "Purged."; } return(lookup); } curl -X PURGE http://...
  141. 141. WARNING Don't use GZIP with ESI asVarnish won't be able to assemble the page

×