使用 ESI 的 Symfony Sulu 清漆

问题描述 投票:0回答:1

我们使用 Symfony (Sulu) 和 Varnish 作为反向代理,基于标签的失效 (xkey) 可以按预期工作。现在我们希望将 ESI 用于我们网站上的动态块,与“主”缓存生命周期分开。

但是每次网页被完全缓存时,即使在硬刷新/清除浏览器缓存或使用新浏览器之后,页面始终显示第一个缓存条目。

我们已在 Symfony 中启用 ESI:

framework:
...
    esi: true
    fragments: { path: /_fragment }

并在我们的 Twig 模板中提供 render_esi:

navbar.html.twig

...
            {{ render_esi(controller('App\\Controller\\Website\\LoginButtonController::renderEsiLoginButton')) }}
            <div class="navbar-main__toggler"></div>
        </div>

LoginButtonController

class LoginButtonController extends AbstractController
{
    public function renderEsiLoginButton(): Response
    {
        $response = $this->render('esi/_login_button.html.twig', ['random_nr' => rand()]);

        $response->setMaxAge(10);
        $response->setSharedMaxAge(10);
        $response->setPublic();

        return $response;
    }
}

_login_button.html.twig

<div class="navbar-main__action-account">
    <div class="account__dropdown">
        <a href="#" class="account__user">{{ random_nr }}</a>
        ...
    </div>
</div>

还有我们的 Varnish default.vcl:

sub vcl_recv {
    call fos_tags_xkey_recv;
    call fos_user_context_recv;
    call sulu_recv;

    // # Add a Surrogate-Capability header to announce ESI
    set req.http.Surrogate-Capability = "abc=ESI/1.0";
...

sub vcl_backend_response {
    set beresp.grace = 2m;

    call fos_user_context_backend_response;
    call sulu_backend_response;

    // Check for ESI acknowledgement and remove Surrogate-Control header
    if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
        unset beresp.http.Surrogate-Control;
        set beresp.do_esi = true;
    }
}
...

我们的 fos_http_cache 配置:

fos_http_cache:
    tags:
        enabled: true
        response_header: xkey
        max_header_value_length: 1024
    proxy_client:
        symfony:
            use_kernel_dispatcher: true

    user_context:
        enabled: true
        role_provider: true
#        user_hash_header: 'X-User-Context-Hash'
        hash_cache_ttl: 900

和sulu http缓存:

when@prod: &prod
    sulu_http_cache:
        debug:
            enabled: false
        tags:
            enabled: true
        cache:
            max_age: 240
            shared_max_age: 480
        proxy_client:
            symfony:
                enabled: false
            varnish:
                enabled: true
                servers: [ '%env(VARNISH_SERVER)%' ]
                tag_mode: purgekeys

使用curl时,我们也可以正确看到esi:include标签:

<span class="navbar-main__action-search-button"></span>

<esi:include src="/_fragment?_hash=HAz3Ym5wXab4GXTRKnq8oUR3WwnGqUpprL0niBc%2BEwg%3D&_path=_format%3Dhtml%26_locale%3Den%26_controller%3DApp%255CController%255CWebsite%255CLoginButtonController%253A%253ArenderEsiLoginButton" onerror="continue" />

<div class="navbar-main__toggler"></div>

但是网页仍然被完整缓存,即使在硬刷新/清除浏览器缓存或使用新浏览器之后,页面始终显示第一个随机数。直到我们完全清除 Varnish 缓存。

我们还缺少什么?

php symfony varnish sulu esi
1个回答
0
投票

从表面上看,你做的一切都是正确的。但是一些有针对性的

varnishlog
命令将使我们更好地了解 Varnish 如何缓存各种片段。

我需要您向我发送以下命令的输出:

sudo varnishlog -g request -q "ReqUrl eq '/'"

我的假设是问题发生在主页上。如果情况并非如此,请更改

varnishlog
命令中的过滤器。

在空缓存上运行此命令非常重要!

当 Varnish 执行各种获取时,我们可以查看日志中的

TTL
标签。这将告诉我们 Varnish 如何决定每个片段的 TTL(通过 VCL 代码中设置的 TTL,或通过
Cache-Control
标头。

日志还会将各种 ESI 子请求作为单独的日志事务返回,从而更容易了解何时发生的情况。

请将日志输出放在您原来的问题中,我将帮助您弄清楚发生了什么。

© www.soinside.com 2019 - 2024. All rights reserved.