Varnish - устаревшее время, кажется, не подтверждает - PullRequest
0 голосов
/ 15 октября 2019

Мы используем Varnish cache 6.2, чтобы располагаться перед нашим бэкэндом WebAPI. Бэкэнд отправляет заголовок элемента управления кэшем обратно на определенные запросы для вещей, которые мы можем кэшировать немного дольше.

Однако - если бэкэнд выключится и останется выключенным, мы отправим stale-while-revalidateчаса.

Итак, типичный заголовок ответа управления кэшем из нашего бэкэнда выглядит так:

public, max-age=30, stale-while-revalidate=3600

В нашем VCL Varnish мы добавили подпрограмму, которая останавливает выборку фона при определенных ошибках. Это нужно для того, чтобы не дать плохому ответу от бэкэнда войти в кеш:

sub vcl_backend_response {
    if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504)
    {
        if (bereq.is_bgfetch)
        {
            return (abandon);
        }

        set beresp.ttl = 1s;
    }
}

Проблема, с которой мы сталкиваемся, проста - Varnish не обновляет элемент в кеше после истечения Max-Age, даже еслибэкэнд доступен. (И произошли изменения в ответе). Мы видели проблемы, когда заголовок «Возраст» от Varnish превышает 200 с ошибочным ответом. Мы также видели случаи, когда заголовок «Возраст» равен 1-3 с, что указывало бы на фоновую выборку (или нормальную выборку).

Это происходит достаточно часто, чтобы мы это замечали - но не при каждом запросе.

Я попробовал простой «проход», такой как в Varnish, например:

sub vcl_recv {
    return(pass);
}

Однако это, похоже, не дало результата.

Может бытьчто-нибудь еще с настройкой Varnish, которое могло бы вызвать ситуацию выше?

EDIT , согласно комментарию, это небольшая вещь, которую мы добавляем к каждому сабвуферу, который взаимодействует с нашим запросом, чтобы увидеть, что на самом делеслучилось:

sub vcl_deliver {
    if (obj.uncacheable) {
        set req.http.x-cache = req.http.x-cache + " uncacheable" ;
    } else {
        set req.http.x-cache = req.http.x-cache + " cached" ;
    }

    set resp.http.x-cache = req.http.x-cache;
}

sub vcl_hit {
    set req.http.x-cache = "hit";
}

1 Ответ

2 голосов
/ 16 октября 2019

Это ожидаемое поведение. После того, как объект был извлечен со стороны бэкэнда в первый раз (то есть t=0), Varnish кэширует его, устанавливая beresp.ttl в 30s и beresp.grace в 3600s. Затем, если вы запросите объект для Varnish, когда t=3000, старый объект будет доставлен на клиентскую сторону (то есть Age: 3000), и будет запущена асинхронная фоновая выборка для обновления кэшированного объекта. Если вы снова запросите объект для Varnish, когда t=3001, если фоновая выборка уже завершила свою работу, будет доставлен свежий объект (т.е. Age: 1). Следующий тест иллюстрирует это поведение:

varnishtest "..."

server s1 {
    rxreq
    txresp -hdr "Cache-Control: public, max-age=1, stale-while-revalidate=60" \
           -hdr "Version: 1"

    rxreq
    txresp -hdr "Cache-Control: public, max-age=1, stale-while-revalidate=60" \
           -hdr "Version: 2"
} -start

varnish v1 -vcl+backend {
} -start

client c1 {
    txreq
    rxresp
    expect resp.http.Version == 1
    expect resp.http.Age == 0

    delay 5.0

    txreq
    rxresp
    expect resp.http.Version == 1
    expect resp.http.Age == 5

    delay 0.1

    txreq
    rxresp
    expect resp.http.Version == 2
    expect resp.http.Age == 0
} -run

varnish v1 -expect client_req == 3

Чтобы обновить объект синхронно, как только элемент в кэше использует свой TTL, вам нужно поиграть с req.grace во время vcl_recv. Возможно, вы захотите установить его на 0s, если бэкэнд исправен. Пожалуйста, проверьте подробности https://varnish -cache.org / docs / trunk / users-guide / vcl-grace.html # misbehaving-servers .

...