PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Varnish – VCL, cache tagging, ESI, invalidacja, DDEV setup

by Henryk Tews / wtorek, 13 października 2020 / Opublikowano w Magento 2, Środowiska

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.

About Henryk Tews

Co możesz przeczytać następne

Magento 2.4.9 – oficjalne wsparcie PHP 8.5, co się zmieniło i jak migrować
Kubernetes dla PHP developera – kubectl debugging, Deployment YAML, HPA, troubleshooting
Własny indekser – mview.xml, flat table, full/partial reindeksacja, triggerowane przez cron
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}