니스가 새로운 데이터를 가져 오는 동안 캐시에서 오래된 데이터를 보내도록 하시겠습니까? 1.88, 12710,/,1,2013-06-24

동적으로 생성 된 페이지 (PHP-FPM, NGINX)를 캐싱하고 있으며 그 앞에 광택이 있습니다. 이는 매우 잘 작동합니다.

그러나 캐시 시간 초과에 도달하면 다음과 같이 표시됩니다.

  • 새로운 고객 요청 페이지
  • 바니시는 캐시 시간 초과를 인식합니다
  • 클라이언트가 기다립니다
  • 바니시는 백엔드에서 새 페이지를 가져옵니다.
  • 니스는 클라이언트에 새 페이지를 전달합니다 (다음 요청을 위해 페이지를 캐시하여 즉시 가져옵니다).

내가하고 싶은 것은 :

  • 클라이언트 요청 페이지
  • 바니시는 타임 아웃을 인식
  • 니스는 클라이언트에게 이전 페이지를 제공합니다
  • 니스는 백엔드에서 새 페이지를 가져 와서 캐시에 넣습니다.

필자의 경우 오래된 정보가 큰 문제가되는 사이트가 아니며 특히 몇 분 후에 캐시 시간 초과에 대해 이야기 할 때 아닙니다.

그러나 나는 처벌 사용자가 줄을 서서 기다리는 것을 원하지 않습니다. 어떤 식 으로든 가능합니까?

예를 들어, 1 분 동안 캐시하도록 구성된 서버에 대해 5 분 동안 포위 공격을 실행 한 샘플 출력이 있습니다.

HTTP/1.1,200,  1.97,  12710,/,1,2013-06-24 00:21:06
...
HTTP/1.1,200,  1.88,  12710,/,1,2013-06-24 00:21:20
...
HTTP/1.1,200,  1.93,  12710,/,1,2013-06-24 00:22:08
...
HTTP/1.1,200,  1.89,  12710,/,1,2013-06-24 00:22:22
...
HTTP/1.1,200,  1.94,  12710,/,1,2013-06-24 00:23:10
...
HTTP/1.1,200,  1.91,  12709,/,1,2013-06-24 00:23:23
...
HTTP/1.1,200,  1.93,  12710,/,1,2013-06-24 00:24:12
...

수백 건의 요청이 빠져 나갔습니다 0.02. 그러나 여전히 원시 HTML을 거의 2 초 동안 기다려야하는 사용자가 있다는 점에 대해 우려하고 있습니다.

여기서 더 잘할 수 없습니까?

( 캐시 동안 Varnish send를 보았습니다. 유사하게 들리지만 정확히하려고하는 것은 아닙니다.)

해결책

Shane Madden의 답변에 솔루션이 포함되어 있지만 바로 그것을 알지 못했습니다. 관련이 없다고 생각했기 때문에 내 질문에 포함시키지 않은 또 다른 세부 사항이 있었지만 실제로는 관련이 있습니다.

현재 사용중인 CMS 솔루션에는 니스 데이터베이스 리스너가 있으므로 내용이 변경된 페이지를 금지하도록 니스에 알리는 기능이 있습니다. PURGE특정 페이지를 금지하라는 정규 표현식으로 요청을 보냈습니다 .

요약하자면, 운이 좋지 않은 사용자가있는 두 가지 경우가 있습니다.

  1. 페이지의 일반 광택 TTL이 만료됩니다
  2. 백엔드 사용자가 콘텐츠를 변경하면 삭제 요청을 니스로 보냅니다.

두 경우 모두 “운이 좋지 않은”사용자가 있습니다. 두 번째 경우에는 백엔드 사용자가 페이지를 변경 한 후 일반적으로 페이지를 확인한다는 사실이 완화됩니다. 그러나 반드시 그런 것은 아닙니다.

그럼에도 불구하고 두 번째 경우에는 해결책을 만들었습니다 (예,이 질문은 첫 번째 경우에 대한 답을 찾는 것으로 시작한다는 것을 알고 있습니다 …

삭제 요청을 보내는 대신 Shanes 제안을 사용하고 VCL을 조정하여 내 광택 데이터베이스 리스너가로 hash_always_miss설정하여 페이지를 가져 오기 위해 특수 요청을 보낼 수 있습니다 true.

현재 아키텍처를 사용하면 실제 비동기 요청을 할 수있는 고급 스러움이 없지만 PHP에서 비동기 GET 요청을 어떻게합니까? 페이지가로드 될 때까지 기다리지 않지만 백엔드에서 페이지를 가져 와서 캐시 할 수있는 니스를 트리거하기에 좋은 GET 요청을 작성할 수있었습니다.

결과적으로 데이터베이스 리스너는 요청을 바니시로 보냈고 특정 페이지를 폴링하는 동안 요청을 “불운”으로 만들지 않았지만 일단 바니시는 백엔드에서 페이지를 완전히 가져 왔습니다 (300ms에서 2 초까지 가능). 갑자기 거기에 있었다.

나는 정상적인 TTL이 떨어졌을 때 동일한 문제를 피하는 방법을 아직 찾지 못했지만 해결책은 Shane이 제안한 것과 정확히 같다고 생각합니다 .wget을 사용하여를 트리거 hash_always_miss하면 목록을 얻을 수있을만큼 똑똑해야합니다. 새로 고침 한 페이지 수



답변

이 문제를 해결하는 데 사용한 솔루션은 페이지의 TTL을 새로 고치기 전에 만료되지 않도록하는 것입니다. 내 시스템 중 하나에서 실행중인 HTTP 클라이언트가 불행한 클라이언트 대신 느린로드를 갖도록 강제하는 것입니다. 의뢰.

필자의 경우 wget에는 cron에서 요청을 표시하고 req.hash_always_miss이를 기반으로 설정하기 위해 특수 헤더를 전송 하여 콘텐츠의 새 사본을 캐시로 가져옵니다.

acl purge {
    "localhost";
}

sub vcl_recv {
    /* other config here */
    if (req.http.X-Varnish-Nuke == "1" && client.ip ~ purge) {
        set req.hash_always_miss = true;
    }
    /* ... */
}

콘텐츠의 경우, 이는 Varnish TTL을 5 분으로 설정하지만 매분마다 캐시 새로 고침 요청을 수행하도록 cron’d wget을 구성하는 것을 의미 할 수 있습니다.


답변

@편집하다:

이 기능이 마스터 브랜치의 최신 버전에서만 구현 된 것 같다는 것을 알려주는 간단한 방법입니다. 귀하의 버전이 아직 유효 하지 않은 정품 확인을 지원하지 않을 수 있습니다 / 게시 한 예제가 제공됩니다. 하나의 불량한 버그가있는 9999/10000 요청이 여전히 백엔드에서 요청이 완료 될 때까지 기다려야합니다.


글쎄, 왜 이전 의견이 작동하지 않는다고 말했는지 100 % 확실하지 않지만 https://www.varnish-software.com/static/book/Saving_a_request.html

  • req.grace- 니스가 오브젝트를 유예 모드로 계속 고려할 수있는 기간을 정의합니다.
  • beresp.grace -beresp.ttl-time Varnish가 오브젝트를 유지하는 기간을 정의합니다.
  • req.grace- 종종 백엔드 상태에 따라 vcl_recv에서 수정됩니다.

나는 현재 매뉴얼에서 말하는 것과 같은 구성을 사용하고 있으며 잘 작동하고 있습니다 … 여기 내 vcl 파일의 스 니펫이 있습니다 …

sub vcl_recv {
    # Cache rules above here...
    if (req.backend.healthy) {
        set req.grace = 30d;
    } else {
        set req.grace = 300d;
    }
}

sub vcl_fetch {
    # Fetch rules above here ...

    # If backend returns 500 error then boost the cache grace period...
    if (beresp.status == 500) {
        set beresp.grace = 10h;
        return (restart);
    }

    # How long carnish should keep the objects in cache..
    set beresp.grace = 1h;

    # Actual TTL of cache - If an object is older than this an update will be triggered to the backend server :)
    set beresp.ttl = 1m;
}

더 긴 백엔드 응답 유예 기간 (내 구성과 같은 500 오류)을 제공하려면 백엔드 프로브를 설정해야합니다 … 백엔드 프로브 사본이 있습니다.

backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .probe = {
        .url = "/nginx-status";
        .timeout = 500 ms;
        .interval = 3s;
        .window = 10;
        .threshold = 4;
    }
}


답변

니스 3에서는 “그레이스 모드”를 통해이 작업을 수행합니다. 설명서 [1]에 따르면 다음 로직을 추가해야합니다.

sub vcl_fetch {
  set beresp.grace = 30m;
} // Makes objects to be cached/stored 30 min beyond its max-age/ttl

sub vcl_recv {
  set req.grace = 60s;
} // Allows varnish to serve objects which expired within last minute.

[1] https://www.varnish-cache.org/docs/3.0/tutorial/handling_misbehaving_servers.html#grace-mode


답변