Ruby on rails 如何在Rails环境中使用Cache control:max age标头控制Varnish和浏览器?

Ruby on rails 如何在Rails环境中使用Cache control:max age标头控制Varnish和浏览器?,ruby-on-rails,caching,http-headers,varnish,Ruby On Rails,Caching,Http Headers,Varnish,最近,我向Rails应用程序堆栈添加了一个Varnish实例。Varnish在其默认配置中使用Cache Control标头缓存特定资源,如下所示: Cache-Control: max-age=86400, public=true 我在控制器中使用expires_in语句实现了这一点: def index expires_in 24.hours, public: true respond_with 'some content' end 这很有效。我没有想到的是,缓存控件头也会影响浏

最近,我向Rails应用程序堆栈添加了一个Varnish实例。Varnish在其默认配置中使用Cache Control标头缓存特定资源,如下所示:

Cache-Control: max-age=86400, public=true
我在控制器中使用expires_in语句实现了这一点:

def index
  expires_in 24.hours, public: true
  respond_with 'some content'
end
这很有效。我没有想到的是,缓存控件头也会影响浏览器。这就导致了一个问题:Varnish和my users浏览器都缓存了某个资源。资源已从varnish中正确清除,但浏览器不会再次尝试请求该资源,除非达到最大期限

所以我想知道我是否应该把“expires_in”和清漆结合使用?我可以在Varnish前面的Nginx或Apache实例中过滤缓存控制头,但这似乎很奇怪

谁能启发我

问候
Felix

这实际上是一个非常好且有效的问题,也是一个非常常见的反向代理问题

问题在于只有一个缓存控制属性,它用于客户端浏览器(专用缓存)和/或代理服务器(共享缓存)。如果您根本不希望第三方代理缓存您的内容,并且希望Varnish(或Rails后端)提供每个请求,则必须从Varnish发送适当的缓存控制头

有关修改后端发送的缓存控制标头的详细信息,请参阅

你可以从两个不同的角度来解决这个问题。如果您希望在Rails后端定义max age,例如为不同的对象指定不同的TTL,您可以使用上面链接中描述的方法

另一种解决方案是根本不从后端发送缓存控制头,而是在varnish vclu fetch()中为对象定义所需的TTL。这是我们采取的办法

在Varnish中,我们有一个默认的TTL为600秒,并为在进行更改时明确清除的页面定义更长的TTL。以下是我们当前的vcl_fetch()定义:

sub vcl_fetch {
  if (req.http.Host ~ "(forum|discus)") {
    # Forum pages are purged explicitly, so cache them for 48h
    set beresp.ttl = 48h;
  }

  if (req.url ~ "^/software/") {
    # Software pages are purged explicitly, so cache them for 48h
    set beresp.ttl = 48h;
  }

  if (req.url ~ "^/search/forum_search_results" ) {
    # We don't want forum search results to be cached for longer than 5 minutes
    set beresp.ttl = 300s;
  }

  if(req.url == "/robots.txt") {
    # Robots.txt is updated rarely and should be cached for 4 days
    # Purge manually as required
    set beresp.ttl = 96h;
  }

  if(beresp.status == 404) {
    # Cache 404 responses for 15 seconds
    set beresp.http.Cache-Control = "max-age=15";
    set beresp.ttl = 15s;
    set beresp.grace = 15s;
  }
}

在本例中,我们根本不从web后端服务器发送缓存控制头。

我遇到了同样的问题。您找到解决方案了吗?谢谢您的详细回答。我们通过简单地将Cache-Control头更改为:Cache-Control:max-age=0 s-maxage=86400,public=true来解决这个问题,这样浏览器就不会缓存资源,而是像Varnish一样缓存共享缓存。错了吗?你也可以用s-maxage。但是,如果您的用户坐在透明代理的后面(一些ISP仍然使用它们),他们也会在24小时内看到缓存的版本。如果需要,可以使用s-maxage。如果没有,则应该从VCL中的响应中重新设置缓存控制头。我将编辑我的答案,以提及s-maxage以及。Thx为您提供有关这方面的信息。我们一定会根据您的解决方案重构和更改。s-maxage绝对是最简单的方法。确保从vcl_deliver中的缓存控制标头中删除s-maxage,以防止下游缓存使用它。您可以使用regsub对其进行过滤。如果您在后端同时设置s-maxage和max age,您将获得一个非常灵活的系统,允许您为Varnish和客户端设置不同的TTL,同时避免在VCL代码中硬编码TTL。