Wbudowany Full Page Cache Magento przechowuje strony w plikach lub Redis. Działa, ale obsługuje requesty wewnątrz PHP – czyli nginx i PHP-FPM i tak muszą wstać do każdego żądania. Varnish działa przed nginxem i serwuje strony z pamięci bez dotykania PHP. Dla sklepu z ruchem to różnica między sekundą a milisekundami odpowiedzi.
Jak działa Varnish z Magento 2
Typowy stack bez Varnish:
Przeglądarka – nginx – PHP-FPM – Magento – Redis/pliki cache
Z Varnish:
Przeglądarka – Varnish – (cache HIT: odpowiedź natychmiast) lub (cache MISS: nginx – PHP-FPM – Magento)
Varnish trzyma strony w pamięci RAM. Cache HIT to dosłownie kilka milisekund – Varnish nie odpala żadnego procesu PHP. Cache MISS trafia do backendu (nginx + PHP), który generuje stronę i oddaje ją Varnishowi do zakeszowania.
Konfiguracja Magento pod Varnish
# Włącz Varnish jako silnik FPC w Magento
bin/magento config:set system/full_page_cache/caching_application 2
# Wygeneruj plik konfiguracyjny VCL dla Varnish
bin/magento varnish:vcl:generate \
--backend-host=nginx \
--backend-port=80 \
--export-version=6 \
--output-file=/etc/varnish/magento.vcl
Magento generuje plik VCL (Varnish Configuration Language) dostosowany do swojej architektury – obsługuje ESI (Edge Side Includes) dla bloków dynamicznych, cache tagging i purge requestów.
Podstawy VCL – jak Varnish podejmuje decyzje
VCL to język konfiguracji Varnish. Kluczowe funkcje które modyfikuje Magento:
# Fragment magento.vcl – uproszczony dla czytelności
sub vcl_recv {
# Nie keszuj requestów z sesją klienta (zalogowany, koszyk)
if (req.http.cookie ~ "PHPSESSID" && req.http.cookie ~ "customer_logged_in") {
return (pass);
}
# Nie keszuj POST requestów
if (req.method == "POST") {
return (pass);
}
# Normalizuj URL - usuń zbędne parametry śledzenia
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|gclid)=") {
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|gclid)=[^&]+", "");
}
return (hash);
}
sub vcl_backend_response {
# Czas keszowania strony produktu - 1 godzina
if (bereq.url ~ "^/catalog/product/view") {
set beresp.ttl = 1h;
}
# Strona główna - 5 minut
if (bereq.url == "/") {
set beresp.ttl = 5m;
}
}
sub vcl_hit {
# Cache HIT - Varnish serwuje z pamięci
return (deliver);
}
Cache Tagging i invalidacja
Magento taguje każdą stronę nagłówkiem X-Magento-Tags zawierającym identyfikatory encji użytych na stronie. Gdy produkt się zmienia, Magento wysyła do Varnish żądanie PURGE z tagiem tego produktu – Varnish usuwa z cache wszystkie strony zawierające ten tag:
<?php
// Tak wygląda nagłówek dla strony produktu
// X-Magento-Tags: cat_p_1234,cat_c_5,store_1
// Magento automatycznie wysyła PURGE gdy zapisujesz produkt
// Możesz też wywołać to ręcznie:
namespace Vendor\Module\Model;
use Magento\CacheInvalidate\Model\PurgeCache;
use Magento\Framework\App\Cache\Tag\Resolver;
class ProductCacheInvalidator
{
public function __construct(
private PurgeCache $purgeCache,
private Resolver $tagResolver
) {}
public function invalidateProduct(\Magento\Catalog\Model\Product $product): void
{
$tags = $this->tagResolver->getTags($product);
// Wyślij żądanie PURGE do Varnish z tagami produktu
$this->purgeCache->sendPurgeRequest(implode('|', $tags));
}
}
ESI – dynamiczne bloki na keszowanych stronach
Problem: strona produktu jest keszowana, ale blok „Ostatnio oglądane” jest per-użytkownik. ESI (Edge Side Includes) rozwiązuje to przez osobne keszowanie bloków:
<!-- Varnish zastępuje ten tag osobnym requestem do backendu --> <esi:include src="/page_cache/block/esi/blocks/" />
Magento automatycznie obsługuje ESI dla bloków oznaczonych jako cacheable="false" w layout XML. Varnish pobiera taki blok osobno, nie blokując keszowania całej strony.
Varnish w DDEV
# .ddev/docker-compose.varnish.yaml
version: '3.6'
services:
varnish:
image: varnish:6.4
ports:
- "6081:6081"
volumes:
- ./magento.vcl:/etc/varnish/default.vcl
environment:
- VARNISH_SIZE=256m
depends_on:
- web
labels:
com.ddev.site-name: ${DDEV_SITENAME}
# Sprawdzenie statystyk Varnish varnishstat # Podgląd logów w czasie rzeczywistym varnishlog -q "ReqURL ~ '/catalog/product'" # Ręczne PURGE całego cache curl -X PURGE http://localhost:6081/.* # Sprawdzenie czy strona pochodzi z Varnish curl -I https://magento2-dev.ddev.site/ | grep X-Cache # X-Cache: HIT lub MISS
Najczęstsze problemy
Strony nie są keszowane mimo Varnisha – najczęstsze przyczyny to ciasteczka sesji w każdym requeście (sprawdź varnishlog co widzi), brak nagłówka Cache-Control: public z Magento (sprawdź konfigurację FPC), albo VCL zbyt agresywnie ustawia pass.
Stale dane po zapisie produktu – sprawdź czy Magento ma poprawny adres Varnish w konfiguracji (Stores – Configuration – Advanced – System – Full Page Cache – Varnish Configuration) i czy port 6081 jest dostępny z kontenera PHP.
Podsumowanie
Varnish to jeden z największych skoków wydajnościowych jakie możesz zrobić dla sklepu Magento pod ruchem. Cache HIT eliminuje PHP z obsługi requestu całkowicie. Kluczem jest dobre zrozumienie VCL i mechanizmu tagowania – wtedy możesz precyzyjnie kontrolować co jest keszowane i jak długo, bez ryzyka serwowania przestarzałych danych.
