4

我在与我的原始服务器相同的机器上有一个 Nginx 反向代理。我希望代理缓存来自源的动态内容,但是当客户端重新验证资源时,我希望代理也重新验证源,而不仅仅是在不检查源的情况下向客户端返回 304。

例如,如果我将 max-age 设置为 60 秒,则代理将在该时间段内愉快地返回 304,而无需检查来源。我已经设置了一个测试,其中源每秒生成一个新的 etag,如下所示(使用 node.js express):

app.get('/dynamic/:file?', function(req, res){
  var filename = req.params.file;
  var filepath = path.join(__dirname, 'files', filename);
  res.setHeader('Cache-Control', 'public, must-revalidate, proxy-revalidate, max-age=60, s-maxage=60');
  res.setHeader('ETag', filename+etagCounter);
  res.sendfile(filepath);
  console.log('request', requestCounter++);
  console.log('etag', etagCounter);
  console.log('date', new Date().toISOString());
});

在 Nginx 中,传递这个请求的路由是这样配置的:

location /cache/ {
  access_log on;

  add_header Vary "Accept-Encoding";

  add_header X-AppServer $upstream_addr;           # Backend Server / Port
  add_header X-AppServer-Status $upstream_status;  # Backend HTTP Status
  add_header X-Cache $upstream_cache_status;       # HIT / MISS / BYPASS / EXPIRED

  proxy_redirect      off;
  proxy_set_header    X-Real-IP            $remote_addr;
  proxy_set_header    X-Forwarded-For      $proxy_add_x_forwarded_for;
  proxy_set_header    X-Forwarded-Proto    $scheme;
  proxy_set_header    Host                 $http_host;
  proxy_set_header    X-NginX-Proxy        true;
  proxy_set_header    Connection           "";

  proxy_cache         one;
  proxy_cache_key     $scheme$proxy_host$uri$is_args$args;

  proxy_pass http://localhost:4444/;
}

当客户端直接与 Express 对话时,我看到 Express 返回 304,但是当 Express 之间有代理时,从不会向 Nginx 返回 304。Nginx 从缓存中提供服务,只有在 max-age 过后才从源站获取资源。

可以肯定的是,我将 etag 刷新间隔设置为 60 秒,将 max-age 设置为 1。因此,Nginx 将每秒从源站获取一个新资源(无需重新验证,因此返回 200 响应),然后返回 304到客户端,直到 60 秒后 etag 更改。

我的结论是 Nginx 永远不会与原始服务器重新验证。只要根据 max-age 认为它需要一个资源,它就会获取一个新的资源副本。

有没有办法做我想做的事?它不尊重代理重新验证标头,还是我没有采取正确的方法?

[编辑]

我已经在这里找到了答案。从这篇文章中,我提出了 2 个解决方案。

1) 缓存响应中的 must-revalidate/proxy-revalidate 应该足以让 nginx 在收到请求中的 max-age=0 时触发重新验证。

2) 当客户端在 CC 标头中发送“无缓存”时,代理肯定应该对源进行重新验证。

从我的测试来看,两者似乎都不起作用。例如,我正在做这样的请求:

curl 'http://localhost:9088/cache/dynamic/image.jpg' -H 'If-None-Match: image.jpg0' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Host: localhost:9088' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Cache-Control: no-cache, max-age=0' -H 'Cookie: octane.sid=s%3AUa64F6fk2Pw0uwZ28e7OICyv.z2FNPYjQ7%2Fn%2F3vZGXV7B3QBYtqN%2FHzjV1e3XTuZcnmwduE4SBFEPDv3zE3zRuA4Ae705RtI6Z%2BBrqJyMveSjNA' -H 'Connection: keep-alive' -H 'If-Modified-Since: Thu, 06 Sep 2012 09:21:53 GMT' --compressed -I

它包含-H 'Cache-Control: no-cache, max-age=0',但我仍然从 nginx 缓存中获取服务内容,而无需检查来源。

Nginx 在这方面表现不佳吗?我正在使用版本 1.5.4

4

0 回答 0