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

Varnish Magento

Varnish Magento

Use varnish reverse proxy cache to increase performance and scalability of Magento. Delivered at Magento Developer Paradise #mdp2011

Alistair Stead

October 08, 2011
Tweet

More Decks by Alistair Stead

Other Decks in Programming

Transcript

  1. WHO AM I • Alistair Stead - @alistairstead • Technical

    Team Lead @ Ibuildings UK / Session Digital • Lead Magento projects for Dreams, 3663, Kookai and others • Author of MageTool and MageTest • Zend Certified Engineer • Over 11 years commercial experience developing in PHP Monday, 6 June 2011
  2. PERFORMANCE AND SCALABILITY Is a hot topic for clients and

    developers alike. Monday, 6 June 2011
  3. HTTP/1.1 200 OK Server: nginx Date: Sun, 05 Jun 2011

    17:40:56 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/5.2.17 Set-Cookie: PHPSESSID=j1cdbj2617abbl8ccsbkd2mt44; path=/ Expires: Mon, 26 Jul 1997 05:00:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post- check=0, pre-check=0 Pragma: no-cache Last-Modified: Sun, 05 Jun 2011 17:40:56 GMT $ curl -I magentocommerce.com Monday, 6 June 2011
  4. Client Application Client Cache GET / HTTP1.1 Host: mystore.com GET

    / HTTP1.1 Host: mystore.com HTTP1.1 200 OK HTTP1.1 200 OK Monday, 6 June 2011
  5. Client Application Client Cache GET / HTTP1.1 Host: mystore.com GET

    / HTTP1.1 Host: mystore.com HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 Monday, 6 June 2011
  6. Client Application Client Cache GET / HTTP1.1 Host: mystore.com HTTP1.1

    200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 Monday, 6 June 2011
  7. Client Application Client Cache GET / HTTP1.1 Host: mystore.com GET

    / HTTP1.1 Host: mystore.com HTTP1.1 200 OK Etag: abcde HTTP1.1 200 OK Etag: abcde HTTP1.1 200 OK Etag: abcde Monday, 6 June 2011
  8. Client Application Client Cache GET / HTTP1.1 Host: mystore.com GET

    / HTTP1.1 Host: mystore.com If-None-Match: abcde HTTP1.1 304 Not Modified HTTP1.1 304 Not Modified HTTP1.1 200 OK Etag: abcde Monday, 6 June 2011
  9. EXPIRATION ALLOWS YOU TO SCALE VALIDATION SAVES BANDWIDTH Fewer requests

    hitting your server and client speed is better too! Monday, 6 June 2011
  10. OUR GOAL IS TO NEVER GENERATE THE SAME RESPONSE TWICE

    HTTP caching can help Monday, 6 June 2011
  11. <?php class Disclosure_Varnish_Model_Observer extends Disclosure_Varnish_Model_Observer_Abstract { /** * Update the

    headers transmitted to allow greater varnish cache hits * * @param $observer */ public function processPreDispatch(Varien_Event_Observer $observer) { if (!$this->isVarnishEnabled()) { return $this; } $routeTtls = $this->_config->getRouteTtls(); $routeName = Mage::app()->getRequest()->getRequestedRouteName(); if (isset($routeTtls[$routeName])) { $observer->getResponse()->setHeader('Cache-Control', $routeTtls[$routeName]['cache_control'], false); } return $this; } } Monday, 6 June 2011
  12. <?xml version="1.0" encoding="UTF-8"?> <config> <ttls> <routes> <cms> <name>cms</name> <cache_control>public, max-age=3600</cache_control>

    </cms> <catalog> <name>catalog</name> <cache_control>public, must-revalidate, max-age=0</cache_control> <actions> <index> <cache_control>private, max-age=0</cache_control> </index> </actions> </catalog> </routes> </ttls> Monday, 6 June 2011
  13. USE VARNISH WITH MAGENTO Add shared cache to reduce the

    load on the application Client Browser Varnish Port 80 Backend Apache Port 8080 Monday, 6 June 2011
  14. Client Application Client Cache Reverse Proxy Cache GET / HTTP1.1

    Host: mystore.com GET / HTTP1.1 Host: mystore.com HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 Monday, 6 June 2011
  15. Client Application Client Cache Reverse Proxy Cache GET / HTTP1.1

    Host: mystore.com HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 Monday, 6 June 2011
  16. Client Application Client Cache Reverse Proxy Cache GET / HTTP1.1

    Host: mystore.com GET / HTTP1.1 Host: mystore.com HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 HTTP1.1 200 OK Cache-Control: max- age=20 Client Client Cache GET / HTTP1.1 Host: mystore.com HTTP1.1 200 OK Cache-Control: max- age=20 Monday, 6 June 2011
  17. Client Application Client Cache Reverse Proxy Cache Client Client Cache

    Gateway Cache Network Proxy Cache max-age s-maxage max-age s-maxage max-age s-maxage max-age max-age Monday, 6 June 2011
  18. VARNISH IS CONFIGURED USING VCL Send the correct headers you

    should not need to do much. Monday, 6 June 2011
  19. sub vcl_recv { set req.http.Surrogate-Capability = "magento=ESI/1.0"; return (lookup); }

    sub vcl_fetch { if (beresp.http.Surrogate-Control ~ "ESI/1.0") { # unset beresp.http.Surrogate-Control; esi; } return (deliver); } sub vcl_deliver { # Set a cache header to allow us to inspect the response # headers during testing if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; set resp.http.X-Cache-Hits = obj.hits; } else { set resp.http.X-Cache = "MISS"; } } Monday, 6 June 2011
  20. /** * Render ESI tags for the block if needed

    * * @param Varien_Event_Observer $observer */ public function renderBlockEsiTag(Varien_Event_Observer $observer) { if (!$this->isEsiEnabled() || !$this->isVarnishEnabled()) { return $this; } $block = $observer->getEvent()->getBlock(); $transport = $observer->getEvent()->getTransport(); $tag = Mage::getModel('varnish/esi_tag_factory')->create($block); if ($transport && $tag) { $transport->setHtml($tag->getHtml()); } return $this; } Monday, 6 June 2011
  21. /** * Render the html for the ESI tag *

    * @return string * @author Alistair Stead **/ public function getHtml() { return sprintf( '<esi:include src="/varnish/esi?attributes=%s"/>', $this->getAttributeHash() ); } Monday, 6 June 2011
  22. class Disclosure_Varnish_EsiController extends Mage_Core_Controller_Front_Action { public function indexAction() { $attributes

    = unserialize(base64_decode($this->getRequest()->getParam('attributes'))); $context = Mage::getModel('varnish/esi_context'); $context->setData($attributes); $processor = Mage::getModel('varnish/esi_processor', $context); // Initialize the layout $this->loadLayout(); Mage::dispatchEvent('varnish_controller_esi_appendbody_before', array("response" => $this->getResponse())); $this->getResponse()->appendBody($processor->render()); Mage::dispatchEvent('varnish_controller_esi_appendbody_after', array("response" => $this->getResponse())); } } Monday, 6 June 2011
  23. TRAFFIC SAMPLE • Product Details page: 58k views per hour

    • Homepage: 50k requests per hour • Main Search : 70k requests per hour • Refined Search (via facets): 20k requests per hour • Add to Basket: 11k requests per hour • Login: 11k requests per hour • Category Pages: 46k requests per hour • Checkout: 6k requests per hour Monday, 6 June 2011
  24. Homepage Category Listings Product Detail Add to cart Login Search

    Purchase 0 375000 750000 1125000 1500000 Client Baseline Magento Baseline Magento Compiler Magento + Varnish FINAL PERFORMANCE RESULTS Monday, 6 June 2011
  25. NON CACHEABLE TRANSACTIONS Add to cart Purchase 0 7500 15000

    22500 30000 Client Baseline Magento Baseline Magento Compiler Magento + Varnish Monday, 6 June 2011
  26. THE TARGET ~ 300K REQUEST We achieved almost 14 x

    that with little effort. Monday, 6 June 2011
  27. IS VARNISH THE BEST SOLUTION? What do we need to

    consider? Monday, 6 June 2011
  28. VARNISH LIMITATIONS • Does not currently support GZIP • Cookies

    need to be managed carefully • Still need SSL endpoint • Routing and URL generation can be tricky • Beware cache stampede • ESI must have a TTL greater than the parent page • Shared cache consider using s-maxage with max-age Monday, 6 June 2011