Performance durch Caching
Fabrizio Branca
System Developer bei AOE media
Mail: mail (at) fabrizio (minus) branca (dot) de
Twitter: @fbrnc
Blog: http://www.fabrizio-branca.de
Ein-
führung
Agenda
Probleme und
Optimierungen
Reverse Proxy
Caching
mit Varnish
Ein-
führung
Agenda
Probleme und
Optimierungen
Reverse Proxy
Caching
mit Varnish
Funktionsweise Cache
Mage::app()->getCacheInstance()
Mage_Core_Model_Cache
Mage::app()->getCache() oder
Mage::app()->getCacheInstance()->getFrontend()
Varien_Cache_Core
… extends
Zend_Cache_Backend
Two-Level Cache
Mehr Details:
http://www.fabrizio-branca.de/magento-caching-internals.html
Ein-
führung
Agenda
Probleme und
Optimierungen
Reverse Proxy
Caching
mit Varnish
Alte Cache-Einträge entfernen
• Problem: Abgelaufene Cache-Einträge werden
nicht gelöscht und sammeln sich an.
• Je größer der Cache, desto langsamer der
Zugriff
• Lösung: Regelmäßig Cache aufräumen
Mage::app()->getCache()->clean(Zend_Cache::CLEANING_MODE_OLD);
• Modul: Aoe_CacheCleaner
http://www.fabrizio-branca.de/magento-automatic-cache-
cleaner.html
• Github:
https://github.com/fbrnc/Aoe_CacheCleaner
Alte Cache-Einträge entfernen
Alte Cache-Einträge entfernen
Probleme im Database Cache Backend:
• Fehlerhaftes SQL
– Einige „?“ fehlen
• Tags werden nicht gelöscht
– In 0.8.22 wurde ein Foreign-Key eingefügt, der die
Tags „on delete“ löscht. In 0.8.27 wurde der Key
wieder entfernt.
• Patch:
https://gist.github.com/971318
Alte Cache-Einträge entfernen
• Wird innerhalb Magento sehr oft verwendet
• Wird vom APC Backend nicht unterstützt
• Kann extrem lange dauern, wenn das File
Backend verwendet wird.
– Lösung: Cache-Commands abfangen, in eine
Queue schreiben und asynchron abarbeiten.
– Beschleunigt außerdem auch den Import-
Vorgang
– http://www.fabrizio-branca.de/magento-
asynchronous-cache.html
– https://github.com/fbrnc/Aoe_AsyncCache
Problem: Tag-Basiertes Löschen
Bug: 1st-Level Cache Priorität
Bug: 1st-Level Cache Priorität
Bug: 1st-Level Cache Priorität
class Varien_Cache_Core extends Zend_Cache_Core {
[…]
public function save($data, $id = null, $tags = array(),
$specificLifetime = false, $priority = 8) {
$tags = $this->_tags($tags);
return parent::save($data, $id, $tags, $specificLifetime, $priority);
}
[…]
}
class Zend_Cache_Backend_TwoLevels […] {
private function _getFastLifetime($lifetime, $priority, $maxLifetime = null) {
[…]
$fastLifetime = (int) ($lifetime / (11 - $priority));
[…]
return $fastLifetime;
}
}
$priority = 10
Bug: 1st-Level Cache Priorität
• Patch:
https://gist.github.com/971320
• Fast cache wird immer neu geschrieben
auto_refresh_fast_cache = true
=> auto_refresh_fast_cache = false
• Kann inzwischen konfiguriert werden (default: false)
• Verzeichnistiefe des File Cache
hashed_directory_level = 1
=> hashed_directory_level = 3
• APC-Parameter (Größe, apc.stat, apc.ttl)
http://www.fabrizio-branca.de/wenn-der-apc-cache-
volllaeuft.html
Weitere Probleme
Ein-
führung
Agenda
Probleme und
Optimierungen
Reverse Proxy
Caching
mit Varnish
Reverse proxy caching
Browser Magento
(Apache + PHP + Mysql)
Request
Response
Reverse proxy caching
Browser Magento
(Apache + PHP + Mysql)
Varnish
Reverse proxy caching
Browser VarnishNginx Magento
(Apache + PHP + Mysql)
-Verschlüsselung /
Entschlüsselung (SSL)
-Kompression
Reverse proxy caching
Browser VarnishNginx Magento
(Apache + PHP + Mysql)
Varnish
HTTP
Accelerator
Caching
Reverse Proxy
Load
Balancer
Failover
system
„Varnish makes websites fly“
• Entwickelt von Poul-Henning Kamp
• Varnish Configuration Language (VCL)
– DSL, wird intern in C Code übersetzt und
dann compiliert
• Varnish überlässt die Thread- und
Speicherverwaltung dem Betriebssystem
• Weitere Tools: varnishtop, varnishlog,…
• Online-Dokumentation:
http://www.varnish-cache.org/docs/2.1/
Varnish
• In Ubuntu:
sudo apt-get install varnish
sudo vi /etc/default/varnish
START=yes
sudo /etc/init.d varnish start
• Wird in Zukunft automatisch gestartet
• Läuft per default auf Port 6081
• Verwendet per default 127.0.0.1:8080 als
Backend
• /etc/varnish/default.vcl
Installation
Request Lifecycle (vereinfacht)
Kompletter Workflow: http://www.varnish-cache.org/trac/wiki/VCLExampleDefault
• cms_index_index (Startseite)
• cms_page_view (CMS Seiten)
• catalog_product_view (Produkt-Singleviews)
• catalog_category_view (Produkt-Listen)
(Muss ggf. an die Anforderungen und Besonderheiten des Shops angepasst
werden)
Cachebare Seiten
aller Page-Requests
(geschätzt)
Dynamische
(benutzerspezifische)
Inhalte
Platzhalter für dynamische Teile
<layout>
<default>
<reference name="right">
<block type="core/text" name="ph_cart" before="-">
<action method="setText"><param><![CDATA[
<div id="cart_sidebar" class="placeholder"
rel="cart_sidebar">Placeholder Cart</div>
]]></param></action>
</block>
<action method="unsetChild"><param>cart_sidebar</param></action>
</reference>
</default>
</layout>
• Sendet HTTP Header um Varnish zu
steuern.
• Bindet JavaScript ein, das die
dynamischen Inhalte holt und die
Platzhalter ersetzt.
• Controller, der die dynamischen Inhalte
ausliefert.
• https://github.com/fbrnc/Aoe_Static
• https://github.com/fbrnc/Aoe_StaticDemo
Modul „Aoe_Static“
Ablauf cachebare Seiten
Seite anfordern (HTTP Request)
Statische Seite wird
ausgeliefert
Seite anfordern
Statische Seite wird ausgeliefert.
Platzhalter für dynamische Teile.
Cache-Control Header
Ajax Request fordert dynamische Inhalte an
und übermittelt gerade angesehenes Produkt
JSON Response mit dynamischen Inhalten
Platzhalter werden ersetzt
Session Cookie wird geschrieben
Seite wird
gerendert
Browser Varnish Magento
Ablauf nicht-cachebare Seiten
Seite anfordern (HTTP Request)
Seite wird ausgeliefert
Seite anfordern
Seite wird
gerendert
Browser Varnish Magento
VCL
sub vcl_recv {
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);
}
VCL
sub vcl_hash {
set req.hash += req.url;
if (req.http.host) {
set req.hash += req.http.host;
} else {
set req.hash += server.ip;
}
return (hash);
}
VCL
sub vcl_fetch {
if (beresp.status == 302 || beresp.status == 301 || beresp.status == 418) {
return (pass);
}
if (beresp.http.aoestatic == "cache") {
remove beresp.http.Set-Cookie;
remove beresp.http.X-Cache;
remove beresp.http.Server;
remove beresp.http.Age;
set beresp.grace = 2m;
set beresp.http.X_AOESTATIC_FETCH = "Removed cookie in vcl_fetch";
}
if (!beresp.cacheable) {
return (pass);
}
return (deliver);
}
VCL
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
set resp.http.Server = "Varnish (HIT)";
} else {
set resp.http.X-Cache = "MISS";
set resp.http.Server = "Varnish (MISS)";
}
}
Demo
Benchmarks
Magento
ohne Cache
0,85
Seiten/Sekunde
2,4
Seiten/Sekunde
416,67
Seiten/Sekunde
Magento mit
APC+File Cache
Magento
mit Varnish
• Anstatt AJAX:
Edge Side Includes „ESI“ (W3C)
<esi:include src="phone/call/getBlock/id/cart_sidebar" />
– Nachteil: langsamer, aufwendiger
• Caching dynamischer Inhalte unter
Berücksichtigung der Session-Id
– Nachteil: weniger Cache Hits
• „Purge“ um geänderte Inhalte zu
aktualisieren
Erweitert
• Varnish (inkl. Dokumentation)
http://www.varnish-cache.org
• Poul-Henning Kamp über Varnish
http://vimeo.com/16676188
• http://www.fabrizio-branca.de
• https://github.com/fbrnc
Weitere Informationen
Fragen?
Mail: mail (at) fabrizio (minus) branca (dot) de
Twitter: @fbrnc
Blog: http://www.fabrizio-branca.de

Performance durch Caching

  • 1.
    Performance durch Caching FabrizioBranca System Developer bei AOE media Mail: mail (at) fabrizio (minus) branca (dot) de Twitter: @fbrnc Blog: http://www.fabrizio-branca.de
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    Alte Cache-Einträge entfernen •Problem: Abgelaufene Cache-Einträge werden nicht gelöscht und sammeln sich an. • Je größer der Cache, desto langsamer der Zugriff
  • 8.
    • Lösung: RegelmäßigCache aufräumen Mage::app()->getCache()->clean(Zend_Cache::CLEANING_MODE_OLD); • Modul: Aoe_CacheCleaner http://www.fabrizio-branca.de/magento-automatic-cache- cleaner.html • Github: https://github.com/fbrnc/Aoe_CacheCleaner Alte Cache-Einträge entfernen
  • 9.
  • 10.
    Probleme im DatabaseCache Backend: • Fehlerhaftes SQL – Einige „?“ fehlen • Tags werden nicht gelöscht – In 0.8.22 wurde ein Foreign-Key eingefügt, der die Tags „on delete“ löscht. In 0.8.27 wurde der Key wieder entfernt. • Patch: https://gist.github.com/971318 Alte Cache-Einträge entfernen
  • 11.
    • Wird innerhalbMagento sehr oft verwendet • Wird vom APC Backend nicht unterstützt • Kann extrem lange dauern, wenn das File Backend verwendet wird. – Lösung: Cache-Commands abfangen, in eine Queue schreiben und asynchron abarbeiten. – Beschleunigt außerdem auch den Import- Vorgang – http://www.fabrizio-branca.de/magento- asynchronous-cache.html – https://github.com/fbrnc/Aoe_AsyncCache Problem: Tag-Basiertes Löschen
  • 12.
  • 13.
  • 14.
    Bug: 1st-Level CachePriorität class Varien_Cache_Core extends Zend_Cache_Core { […] public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8) { $tags = $this->_tags($tags); return parent::save($data, $id, $tags, $specificLifetime, $priority); } […] } class Zend_Cache_Backend_TwoLevels […] { private function _getFastLifetime($lifetime, $priority, $maxLifetime = null) { […] $fastLifetime = (int) ($lifetime / (11 - $priority)); […] return $fastLifetime; } } $priority = 10
  • 15.
    Bug: 1st-Level CachePriorität • Patch: https://gist.github.com/971320
  • 16.
    • Fast cachewird immer neu geschrieben auto_refresh_fast_cache = true => auto_refresh_fast_cache = false • Kann inzwischen konfiguriert werden (default: false) • Verzeichnistiefe des File Cache hashed_directory_level = 1 => hashed_directory_level = 3 • APC-Parameter (Größe, apc.stat, apc.ttl) http://www.fabrizio-branca.de/wenn-der-apc-cache- volllaeuft.html Weitere Probleme
  • 17.
  • 18.
    Reverse proxy caching BrowserMagento (Apache + PHP + Mysql) Request Response
  • 19.
    Reverse proxy caching BrowserMagento (Apache + PHP + Mysql) Varnish
  • 20.
    Reverse proxy caching BrowserVarnishNginx Magento (Apache + PHP + Mysql) -Verschlüsselung / Entschlüsselung (SSL) -Kompression
  • 21.
    Reverse proxy caching BrowserVarnishNginx Magento (Apache + PHP + Mysql)
  • 22.
  • 23.
    • Entwickelt vonPoul-Henning Kamp • Varnish Configuration Language (VCL) – DSL, wird intern in C Code übersetzt und dann compiliert • Varnish überlässt die Thread- und Speicherverwaltung dem Betriebssystem • Weitere Tools: varnishtop, varnishlog,… • Online-Dokumentation: http://www.varnish-cache.org/docs/2.1/ Varnish
  • 24.
    • In Ubuntu: sudoapt-get install varnish sudo vi /etc/default/varnish START=yes sudo /etc/init.d varnish start • Wird in Zukunft automatisch gestartet • Läuft per default auf Port 6081 • Verwendet per default 127.0.0.1:8080 als Backend • /etc/varnish/default.vcl Installation
  • 25.
    Request Lifecycle (vereinfacht) KompletterWorkflow: http://www.varnish-cache.org/trac/wiki/VCLExampleDefault
  • 26.
    • cms_index_index (Startseite) •cms_page_view (CMS Seiten) • catalog_product_view (Produkt-Singleviews) • catalog_category_view (Produkt-Listen) (Muss ggf. an die Anforderungen und Besonderheiten des Shops angepasst werden) Cachebare Seiten aller Page-Requests (geschätzt)
  • 28.
  • 29.
    Platzhalter für dynamischeTeile <layout> <default> <reference name="right"> <block type="core/text" name="ph_cart" before="-"> <action method="setText"><param><![CDATA[ <div id="cart_sidebar" class="placeholder" rel="cart_sidebar">Placeholder Cart</div> ]]></param></action> </block> <action method="unsetChild"><param>cart_sidebar</param></action> </reference> </default> </layout>
  • 30.
    • Sendet HTTPHeader um Varnish zu steuern. • Bindet JavaScript ein, das die dynamischen Inhalte holt und die Platzhalter ersetzt. • Controller, der die dynamischen Inhalte ausliefert. • https://github.com/fbrnc/Aoe_Static • https://github.com/fbrnc/Aoe_StaticDemo Modul „Aoe_Static“
  • 31.
    Ablauf cachebare Seiten Seiteanfordern (HTTP Request) Statische Seite wird ausgeliefert Seite anfordern Statische Seite wird ausgeliefert. Platzhalter für dynamische Teile. Cache-Control Header Ajax Request fordert dynamische Inhalte an und übermittelt gerade angesehenes Produkt JSON Response mit dynamischen Inhalten Platzhalter werden ersetzt Session Cookie wird geschrieben Seite wird gerendert Browser Varnish Magento
  • 32.
    Ablauf nicht-cachebare Seiten Seiteanfordern (HTTP Request) Seite wird ausgeliefert Seite anfordern Seite wird gerendert Browser Varnish Magento
  • 33.
    VCL sub vcl_recv { 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); }
  • 34.
    VCL sub vcl_hash { setreq.hash += req.url; if (req.http.host) { set req.hash += req.http.host; } else { set req.hash += server.ip; } return (hash); }
  • 35.
    VCL sub vcl_fetch { if(beresp.status == 302 || beresp.status == 301 || beresp.status == 418) { return (pass); } if (beresp.http.aoestatic == "cache") { remove beresp.http.Set-Cookie; remove beresp.http.X-Cache; remove beresp.http.Server; remove beresp.http.Age; set beresp.grace = 2m; set beresp.http.X_AOESTATIC_FETCH = "Removed cookie in vcl_fetch"; } if (!beresp.cacheable) { return (pass); } return (deliver); }
  • 36.
    VCL sub vcl_deliver { if(obj.hits > 0) { set resp.http.X-Cache = "HIT"; set resp.http.Server = "Varnish (HIT)"; } else { set resp.http.X-Cache = "MISS"; set resp.http.Server = "Varnish (MISS)"; } }
  • 37.
  • 38.
  • 39.
    • Anstatt AJAX: EdgeSide Includes „ESI“ (W3C) <esi:include src="phone/call/getBlock/id/cart_sidebar" /> – Nachteil: langsamer, aufwendiger • Caching dynamischer Inhalte unter Berücksichtigung der Session-Id – Nachteil: weniger Cache Hits • „Purge“ um geänderte Inhalte zu aktualisieren Erweitert
  • 40.
    • Varnish (inkl.Dokumentation) http://www.varnish-cache.org • Poul-Henning Kamp über Varnish http://vimeo.com/16676188 • http://www.fabrizio-branca.de • https://github.com/fbrnc Weitere Informationen
  • 41.
    Fragen? Mail: mail (at)fabrizio (minus) branca (dot) de Twitter: @fbrnc Blog: http://www.fabrizio-branca.de