1、浏览器第一次请求图片资源文件,服务端计算出etag标识,并通过响应头告诉浏览器,如标红部分
-
Remote Address:10.70.128.75:8080
-
Request URL:http://wap.cmread.com/r/cover_file/8231/392268231/20140212102919/cover75100.jpg
-
Request Method:GET
-
Status Code:200 OK
2、浏览器第二次请求图片资源文件,浏览器会将之前拿到的etag标识增加到请求头的if-none-match中,
服务端解析到文件字段,则会取文件当前etag与请求头中的if-none-match内容进行对比,如果一致,则反馈304 not modified
-
Remote Address:10.70.128.75:8080
-
Request URL:http://wap.cmread.com/r/cover_file/8231/392268231/20140212102919/cover75100.jpg
-
Request Method:GET
-
Status Code:304 Not Modified
3、关于集群业务到底是否适合使用etag
之前网上主流说法是采用集群方式部署的业务不适合用etag来进行缓存,原因是etag会根据inode进行计算,导致不同主机计算出来的etag可能不同。
针对这个问题,我在内网进行验证发现不同主机(跨机房)对同一图片资源生成的Etag是完全相同的,与网上的说法并不一至。
分析apache-tomcat-7.0.54源码发现,etag的计算方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
apache-tomcat-7.0.54-src/java/org/apache/naming/resources/ResourceAttributes.java
/**
* Get ETag.
*
* @return strong ETag if available, else weak ETag.
*/
public String getETag() {
String result =
null
;
if
(attributes !=
null
) {
Attribute attribute = attributes.get(ETAG);
if
(attribute !=
null
) {
try
{
result = attribute.get().toString();
}
catch
(NamingException e) {
// No value for the attribute
}
}
}
if
(result ==
null
) {
if
(strongETag !=
null
) {
// The strong ETag must always be calculated by the resources
result = strongETag;
}
else
{
// The weakETag is contentLength + lastModified
if
(weakETag ==
null
) {
long contentLength = getContentLength();
long lastModified = getLastModified();
if
((contentLength >= 0) || (lastModified >= 0)) {
weakETag =
"W/\""
+ contentLength +
"-"
+
lastModified +
"\""
;
}
}
result = weakETag;
}
}
return
result;
}
|
可以看出,etag仅根据contentLength和lastModified进行计算,并没有使用到文件inode,所以对于同一个文件只要文件大小 和最后修改时间完全一致,则在不同的主机上计算出来的etag是完全一致的。