Подтвердить что ты не робот

Как заставить Cache Tagging работать с FOSHttpCacheBundle и Varnish?

Я настроил Symfony и FOSHttpCacheBundle (следуя инструкциям конфигурации Varnish в документации FOSHttpCache).

Я добавил к контроллеру действие, которое добавляет тег test в HTTP-заголовке ответа:

<?php

use FOS\HttpCacheBundle\Configuration\Tag;

class MyController extends Controller
{
    /**
     * @Route("/test1", name="acme_my_test1")
     * @Tag("test")
     */
    public function test1Action()
    {
        return new Response(rand(0, 1000));
    }
}

Однако, когда я вызываю URL /test1, число меняется, показывая, что кеш не активен. Обратите внимание, что мое приложение не использует cookie, и я могу проверить, что заголовок X-Cache-Tags отправлен в Varnish (который отбрасывает его в ответ на браузер, благодаря директиве vlc_deliver).

Есть ли что-то, что я бы пропустил в конфигурации? Оба Varnish и Nginx работают на одном сервере.

Вот конфигурация, связанная с кешем HTTP в моем файле Symfony config.yml:

framework:
    trusted_hosts:   ~
    trusted_proxies:  [127.0.0.1]

fos_http_cache:
    proxy_client:
        varnish:
            servers: 127.0.0.1:80
            base_url: mywebsite.localhost.com
    tags:
        enabled: true

И настройка лака в /etc/varnish/default.vcl:

vcl 4.0;

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

acl invalidators {
    "localhost";
}

sub vcl_recv {
    if (req.http.X-Forwarded-Proto == "https" ) {
        set req.http.X-Forwarded-Port = "443";
    } else {
        set req.http.X-Forwarded-Port = "80";
    }

    set req.http.Surrogate-Capability = "abc=ESI/1.0";

    if (req.method == "PURGE") {
        if (!client.ip ~ invalidators) {
            return (synth(405, "Not allowed"));
        }
        return (purge);
    }

    if (req.http.Cache-Control ~ "no-cache" && client.ip ~ invalidators) {
        set req.hash_always_miss = true;
    }

    if (req.method == "BAN") {
        if (!client.ip ~ invalidators) {
            return (synth(405, "Not allowed"));
        }

        if (req.http.X-Cache-Tags) {
            ban("obj.http.X-Host ~ " + req.http.X-Host
                + " && obj.http.X-Url ~ " + req.http.X-Url
                + " && obj.http.content-type ~ " + req.http.X-Content-Type
                + " && obj.http.X-Cache-Tags ~ " + req.http.X-Cache-Tags
            );
        } else {
            ban("obj.http.X-Host ~ " + req.http.X-Host
                + " && obj.http.X-Url ~ " + req.http.X-Url
                + " && obj.http.content-type ~ " + req.http.X-Content-Type
            );
        }

        return (synth(200, "Banned"));
    }
}

sub vcl_backend_response {
    set beresp.http.X-Url = bereq.url;
    set beresp.http.X-Host = bereq.http.host;

    if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
        unset beresp.http.Surrogate-Control;
        set beresp.do_esi = true;
    }
}

sub vcl_deliver {
    if (!resp.http.X-Cache-Debug) {
        unset resp.http.X-Url;
        unset resp.http.X-Host;
        unset resp.http.X-Cache-Tags;
    }
}
4b9b3361

Ответ 1

Хорошо, я нашел его. Все было хорошо в моей конфигурации, за исключением того, что мне пришлось добавить некоторые заголовки истечения. Я думал, что заголовок тегов был достаточно, но необходим слишком длинный заголовок срока действия.

Действие должно выглядеть так:

<?php

use FOS\HttpCacheBundle\Configuration\Tag;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;

class MyController extends Controller
{
    /**
     * @Route("/test1", name="acme_my_test1")
     * @Tag("test")
     * @Cache(expires="+1 year")
     */
    public function test1Action()
    {
        return new Response(rand(0, 1000));
    }
}

У меня все еще есть небольшая проблема с тегами и тегами ESI, но это выходит за рамки этого вопроса.