caching - Varnish 缓存对象很快过期

标签 caching varnish varnish-vcl

我的 Varnish (v3.0.2) 缓存出现问题,尽管 TTL 为 24 小时,但它仍然在不到 60 秒后重置对象的缓存,cookie 被剥离,内容编码标准化,非关键 header 未设置, Cache-Control 设置为 public,s-maxage=86400 等。

出于某种原因,如果您在一分钟内重复访问以下 URL,您可以看到 Age 慢慢上升然后达到零(X-Cache 返回 MISS):

http://data.eyewire.org/volume/83329/chunk/0/1/0/1/tile/xz/32:64

没有 n_lru_nuked 对象,缓存超过 60GB。我看了 Varnish 日志,可能看到了 ExpBan 正在进行的一些事情,但我终生无法弄清楚原因。

以下是我的 vcl 文件的一些关键部分:

sub vcl_recv {
  set req.grace = 120s;

   # normalize Accept-Encoding to reduce vary
  if (req.http.Accept-Encoding) {
    if (req.http.User-Agent ~ "MSIE 6") {
      unset req.http.Accept-Encoding;
    } 
    elsif (req.http.Accept-Encoding ~ "gzip") {
      set req.http.Accept-Encoding = "gzip";
    } 
    elsif (req.http.Accept-Encoding ~ "deflate") {
      set req.http.Accept-Encoding = "deflate";
    } 
    else {
      unset req.http.Accept-Encoding;
    }
  }

  # This uses the ACL action called "purge". Basically if a request to
  # PURGE the cache comes from anywhere other than localhost, ignore it.
  if (req.request == "PURGE") 
    {if (!client.ip ~ purge)
      {error 405 "Not allowed.";}
    return(lookup);}

  if (req.http.Upgrade ~ "(?i)websocket") {
    return (pipe);
  }

  # ....

  if ( req.http.host ~ "data\.eyewire\.org" ) {
    unset req.http.Cookie;
    unset req.http.Accept-Language;
    unset req.http.Expires;
    unset req.http.Cache-Control;
    unset req.http.User-Agent;
    return(lookup);
  }

  # ....
}


sub vcl_fetch {
  # ....

  if ( req.http.host ~ "data.eyewire.org" ) {
    if ( req.url ~ "^/volume" ) {
      unset beresp.http.Set-Cookie;
      set beresp.ttl = 24h;
      set beresp.http.Cache-Control = "public, s-maxage=86400";
      set beresp.http.X-TTL = beresp.ttl;
      return(deliver);
    }
    elsif (req.url ~ "^/cell") {
      set beresp.ttl = 1h;
      return(hit_for_pass);
    }
  }
}

# from http://blog.bigdinosaur.org/adventures-in-varnish/
sub vcl_pass {
  set bereq.http.connection = "close";
  if (req.http.X-Forwarded-For) {
      set bereq.http.X-Forwarded-For = req.http.X-Forwarded-For;
  }
  else {
      set bereq.http.X-Forwarded-For = regsub(client.ip, ":.*", "");
  }
}

# from http://blog.bigdinosaur.org/adventures-in-varnish/
sub vcl_pipe {
  #we need to copy the upgrade header
  if (req.http.upgrade) {
      set bereq.http.upgrade = req.http.upgrade;
      set bereq.http.connection = req.http.connection;
  }

  set bereq.http.connection = "close";
  if (req.http.X-Forwarded-For) {
      set bereq.http.X-Forwarded-For = req.http.X-Forwarded-For;
  }
  else {
      set bereq.http.X-Forwarded-For = regsub(client.ip, ":.*", "");
  }
}

# from http://blog.bigdinosaur.org/adventures-in-varnish/
sub vcl_hit {
  if (req.request == "PURGE") {
      purge;
      error 200 "Purged.";
  }
}

# from http://blog.bigdinosaur.org/adventures-in-varnish/
sub vcl_miss {
  if (req.request == "PURGE") {
      purge;
      error 200 "Purged.";
  }
}

sub vcl_deliver {  
    # Display hit/miss info
    if (obj.hits > 0) {
      set resp.http.X-Cache = "HIT";
      set resp.http.X-Cache-Hits = obj.hits;
    }
    else {
        set resp.http.X-Cache = "MISS";
    }

    # Security Non-Disclosure
    remove resp.http.X-Varnish;
    remove resp.http.X-Powered-By;
    remove resp.http.Server;

    return(deliver);
}

谢谢!

编辑:仅供引用:我不得不恢复对 VCL 的一些更改以解决生产中的问题,但问题本质上仍然相同。

最佳答案

我遇到了相同的行为,即命中率上升,并且似乎没有任何理由清除高速缓存。经过一番研究后,我发现原因是有所不同:Accept-Encoding,用户代理 header ,为每个用户代理保存了不同的缓存。

尝试仅为Accept-Encoding设置一个variable header 。

关于caching - Varnish 缓存对象很快过期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25860516/

相关文章:

c# - 我怎样才能让这个并发字典用计时器过期?

c++ - 如何在不污染缓存的情况下读取大量数据?

java - Hazelcast Map TTL 不适用于 spring 缓存抽象

php - Codeigniter : Varnish and Cookie/Session conflict

Varnish vcl_recv的默认行为

caching - 如何返回(传递)所有不在 acl 中的主机 - Varnish

restart - Varnish 重启跟踪

Varnish 自动将负载均衡器 IP 添加到 X-Forwarded-For header

c# - 按相等缓存 LINQ 表达式

apache - Varnish 的优雅关闭