HTTP缓存和ETAG标头

时间:2014-12-04 09:17:17

标签: caching nginx varnish etag

经过大量不成功的研究后,我想知道是否可以使用nginx或varnish cache函数来检查标题中包含etag属性所包含的数据新鲜度。

使用图表更容易解释这种情况,请参阅下文:

http://image.noelshack.com/fichiers/2014/49/1417684577-cache-nginx.png

您认为此用例是否可行?

谢谢你,对不起我的英文:s

1 个答案:

答案 0 :(得分:0)

您可以使用清漆stale-while-revalidate执行类似操作,但不完全相同。使用前端缓存的想法是,当后端将对象发送到缓存时,它会设置一个Expires头,该头将允许缓存提供此内容而不会打扰后端。如果缓存会使用后端检查每个请求,那么获得的速度就不会太快,因为您最终会等待每个请求的后端。

要解决此问题,您应该相应地设置Expires标头,并且/或者如果突然您需要在Expires之前删除陈旧内容,则清除/禁止URL。这样缓存就会从自己的缓存中发送内容,或者如果没有它或者它已经过时,则从后端获取内容。

编辑:

我已经使用Varnish 4.0.1进行了测试,它支持对后端的条件请求。

我的测试设置是带有ExpiresByType text/html "access plus 5 seconds"

的Apache虚拟主机

结果:

*   << BeReq    >> 65539
-   Begin          bereq 65538 bgfetch
-   Timestamp      Start: 1418403624.141695 0.000000 0.000000
-   BereqMethod    GET
-   BereqURL       /prueba.html
-   BereqProtocol  HTTP/1.1
-   BereqHeader    User-Agent: lwp-request/6.03 libwww-perl/6.05
-   BereqHeader    X-Forwarded-For: 127.0.0.1
-   BereqHeader    Host: localtest
-   BereqHeader    Surrogate-Capability: key=ESI/1.0
-   BereqHeader    Accept-Encoding: gzip
-   BereqHeader    If-Modified-Since: Thu, 01 Dec 2011 10:37:55 GMT
-   BereqHeader    If-None-Match: "3e8be5-46-4b30571f606c0"
-   BereqHeader    X-Varnish: 65539
-   VCL_call       BACKEND_FETCH
-   VCL_return     fetch
-   Backend        17 vdir server1(127.0.0.1,,80)
-   Timestamp      Bereq: 1418403624.141869 0.000174 0.000174
-   Timestamp      Beresp: 1418403624.143205 0.001510 0.001336
-   BerespProtocol HTTP/1.1
-   BerespStatus   304
-   BerespReason   Not Modified
-   BerespHeader   Date: Fri, 12 Dec 2014 17:00:24 GMT
-   BerespHeader   Server: Apache
-   BerespHeader   ETag: "3e8be5-46-4b30571f606c0"
-   BerespHeader   Expires: Fri, 12 Dec 2014 17:00:29 GMT
-   BerespHeader   Cache-Control: max-age=5
-   TTL            RFC 5 -1 -1 1418403624 1418403624 1418403624 1418403629 5
-   BerespProtocol HTTP/1.1
-   BerespStatus   200
-   BerespReason   OK
-   BerespHeader   Last-Modified: Thu, 01 Dec 2011 10:37:55 GMT
-   BerespHeader   Content-Type: text/html
-   VCL_call       BACKEND_RESPONSE
-   TTL            VCL 5 21600 0 1418403624
-   VCL_return     deliver
-   Storage        malloc s0
-   ObjProtocol    HTTP/1.1
-   ObjStatus      200
-   ObjReason      OK
-   ObjHeader      Date: Fri, 12 Dec 2014 17:00:24 GMT
-   ObjHeader      Server: Apache
-   ObjHeader      ETag: "3e8be5-46-4b30571f606c0"
-   ObjHeader      Expires: Fri, 12 Dec 2014 17:00:29 GMT
-   ObjHeader      Cache-Control: max-age=5
-   ObjHeader      Last-Modified: Thu, 01 Dec 2011 10:37:55 GMT
-   ObjHeader      Content-Type: text/html
-   BackendReuse   17 server1(127.0.0.1,,80)
-   Timestamp      BerespBody: 1418403624.143465 0.001770 0.000260
-   Length         70
-   BereqAcct      289 0 289 181 0 181
-   End

在这里你可以看到我要求一个过时的对象,所以清漆去获取它,并以这种方式请求它:

-   BereqURL       /prueba.html
-   BereqHeader    If-Modified-Since: Thu, 01 Dec 2011 10:37:55 GMT
-   BereqHeader    If-None-Match: "3e8be5-46-4b30571f606c0"

后端回答:

-   BerespStatus   304
-   BerespReason   Not Modified
-   BerespHeader   Date: Fri, 12 Dec 2014 17:00:24 GMT
-   BerespHeader   ETag: "3e8be5-46-4b30571f606c0"
-   BerespHeader   Expires: Fri, 12 Dec 2014 17:00:29 GMT
-   BerespHeader   Cache-Control: max-age=5

因此没有传输正文字节,而varnish使用新更新的标题刷新它的对象。

也许这就是你想要的行为。

请注意,确认条件(GETIf-Modified-Since)的If-None-Match请求只会返回304 Not Modified,某些标题和正文(完全是就好像它是具有相同条件的HEAD请求一样),如果它没有验证它将返回标题和新主体。但是,未验证的HEAD个请求会返回200 OK NO 正文,强制您使用GET重新请求它。

HTTP/1.1 Method Definitions RFC

  

HEAD方法与GET相同,只是服务器不能在响应中返回消息体。元信息   包含在HTTP头中以响应HEAD请求应该是   与响应GET请求时发送的信息相同。