首先看一下code 412的解释
服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。这个状态码允许客户端在获取资源时在请求的元信息(请求头字段数据)中设置先决条件,以此避免该请求方法被应用到其希望的内容以外的资源上。
客户做了更换源站的动作,大量突增412!!!其中发现一个很重要的细节
第一次未缓存过的时候,可以正常下载
[xxxx ~]$ wget -SO /dev/null http://fxpk.yingyonghui.com/bbs/METAL_SLUG_3_v1.6_d4dsf.xpk --header "if-match: CDN" -e http-proxy=222.186.129.161
--2016-04-25 10:09:43-- http://fxpk.yingyonghui.com/bbs/METAL_SLUG_3_v1.6_d4dsf.xpk
Connecting to 222.186.129.161:80... connected.
Proxy request sent, awaiting response...
HTTP/1.1 200 OK
Date: Mon, 25 Apr 2016 02:09:43 GMT
Content-Length: 61435881
Accept-Ranges: bytes
Content-Type: application/zip
Last-Modified: Fri, 30 Jan 2015 09:16:32 GMT
Cache-Control: public, max-age=31536000
Connection: Close
ETag: "lkl1zHu_x9M1bGJ4AGHx6GyqGA_w"
Server: nginx/1.4.4
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Log, X-Reqid
Access-Control-Max-Age: 2592000
Content-Transfer-Encoding: binary
X-Log: mc.g;IO:1
X-Reqid: rJcAACeB9P0leEgU
X-Qiniu-Zone: 0
Content-Disposition: inline; filename="METAL_SLUG_3_v1.6_d4dsf.xpk"
X-Via: 1.1 xxz206:8104 (Cdn Cache Server V2.0), 1.1 jtzh97:8 (Cdn Cache Server V2.0)
Fw-Via: MISS from 222.186.129.161
Length: 61435881 (59M) [application/zip]
Saving to: `/dev/null'
7% [==============> ] 4,858,880 4.40M/s
缓存住以后,就不能下载了
[xxxx ~]$ wget -SO /dev/null http://fxpk.yingyonghui.com/bbs/METAL_SLUG_3_v1.6_d4dsf.xpk --header "if-match: CDN" -e http-proxy=222.186.129.161
--2016-04-25 10:14:19-- http://fxpk.yingyonghui.com/bbs/METAL_SLUG_3_v1.6_d4dsf.xpk
Connecting to 222.186.129.161:80... connected.
Proxy request sent, awaiting response...
HTTP/1.0 412 Precondition Failed
Date: Mon, 25 Apr 2016 02:14:19 GMT
Content-Length: 168
Connection: Close
Fw-Via: LGenerate MISS from 222.186.129.161
2016-04-25 10:14:20 ERROR 412: Precondition Failed.
使用正确 Etag 之后,又可以正常下载了
[xxxx ~]$ wget -SO /dev/null http://fxpk.yingyonghui.com/bbs/METAL_SLUG_3_v1.6_d4dsf.xpk --header 'if-match: "lkl1zHu_x9M1bGJ4AGHx6GyqGA_w"' -e http-proxy=222.186.129.161
--2016-04-25 11:02:08-- http://fxpk.yingyonghui.com/bbs/METAL_SLUG_3_v1.6_d4dsf.xpk
Connecting to 222.186.129.161:80... connected.
Proxy request sent, awaiting response...
HTTP/1.0 200 OK
Date: Mon, 25 Apr 2016 03:02:08 GMT
Content-Length: 61435881
Accept-Ranges: bytes
Content-Type: application/zip
Last-Modified: Fri, 30 Jan 2015 09:16:32 GMT
Cache-Control: public, max-age=31536000
Connection: Close
ETag: "lkl1zHu_x9M1bGJ4AGHx6GyqGA_w"
Server: nginx/1.8.0
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Log, X-Reqid
Access-Control-Max-Age: 2592000
Content-Transfer-Encoding: binary
X-Log: mc.g:1;IO:1
X-Reqid: yEwAAO7aYxWvekgU
X-Qiniu-Zone: 0
Content-Disposition: inline; filename="METAL_SLUG_3_v1.6_d4dsf.xpk"
X-Via: 1.1 xxz206:8104 (Cdn Cache Server V2.0), 1.1 jtzh97:8 (Cdn Cache Server V2.0)
Fw-Via: DISK HIT from 222.186.129.161
Length: 61435881 (59M) [application/zip]
Saving to: `/dev/null'
100%[===================================================================================================================================================================================================>] 61,435,881 43.9M/s in 1.3s
2016-04-25 11:02:09 (43.9 MB/s) - `/dev/null' saved [61435881/61435881]
结论:
1. 为什么我们有大量 412?
因为我们做了鉴权,而有很多盗链存在,因此有 412 记录
2. 为什么源站就没有 412?
因为源站(网宿)根本没有鉴权,携带任何 Etag,甚至不携带,都可以下载
客户在更换的七牛源站没有做过鉴权的设置,在咱们这也没有ftag的设置,但是会返回412 。
412 出现的条件是
1. 当源站给了 ETag 信息
2. 当访问者在请求头了给了 If-match 字段
3. 当 If-Match 字段的数据与 ETag 数据不对应的时候
以上 3 种情况同时出现才会有 412
利用 sdump 抓包发现,确实是客户端自身的问题
客户端请求时强行携带了一个错误的 If-Match 字段,导致 FCD 验证失败返回 412
4 0.040407 183.216.28.71 -> 223.99.243.217 HTTP 275 GET /bbs/Grand_Theft_Auto_v1.07_han.xpk HTTP/1.1
0000 6c 92 bf 13 c1 a2 70 f9 6d fa 02 d8 08 00 45 04 l.....p.m.....E.
0010 01 05 f3 76 40 00 36 06 a9 1b b7 d8 1c 47 df 63 [email protected]
0020 f3 d9 9b 0b 00 50 a3 be 0d 1f a2 9b 7d 8c 50 18 .....P......}.P.
0030 01 c9 48 e5 00 00 47 45 54 20 2f 62 62 73 2f 47 ..H...GET /bbs/G
0040 72 61 6e 64 5f 54 68 65 66 74 5f 41 75 74 6f 5f rand_Theft_Auto_
0050 76 31 2e 30 37 5f 68 61 6e 2e 78 70 6b 20 48 54 v1.07_han.xpk HT
0060 54 50 2f 31 2e 31 0d 0a 49 66 2d 4d 61 74 63 68 TP/1.1..If-Match
0070 3a 20 22 35 35 62 38 39 62 32 36 2d 33 65 39 34 : "55b89b26-3e94
0080 36 35 30 31 22 0d 0a 52 61 6e 67 65 3a 20 62 79 6501"..Range: by
0090 74 65 73 3d 33 33 37 39 33 37 39 32 2d 0d 0a 43 tes=33793792-..C
00a0 6c 69 65 6e 74 2d 56 65 72 73 69 6f 6e 3a 20 33 lient-Version: 3
00b0 30 30 35 34 36 36 34 0d 0a 48 6f 73 74 3a 20 66 0054664..Host: f
00c0 78 70 6b 2e 79 69 6e 67 79 6f 6e 67 68 75 69 2e xpk.yingyonghui.
00d0 63 6f 6d 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a com..Connection:
00e0 20 4b 65 65 70 2d 41 6c 69 76 65 0d 0a 55 73 65 Keep-Alive..Use
00f0 72 2d 41 67 65 6e 74 3a 20 41 6e 64 72 6f 69 64 r-Agent: Android
0100 44 6f 77 6e 6c 6f 61 64 4d 61 6e 61 67 65 72 0d DownloadManager.
0110 0a 0d 0a
虽然判断是客户端问题,但是比较疑惑为什么会有大量的客户端携带错误的If-Match 字段,然后为了用户的访问效果,忽略了ETAG。
总结:
1.为什么不同的节点会缓存不同的ETag?
客户之前源站 返回过Etag,变更七牛的源站之后,同一个文件生成的ETag值不一样,节点缓存的是之前源站的ETag值,源站变更之后,没有做刷新,没有及时缓存到新的ETag值,附件'七牛源站'返回的信息,可以看到X-Via的CDN信息 ,附件‘之前源站’就没有,显示只是一台服务器。所以出现不同的ETag值,是因为访问到了不同的源站。
客户自己源站服务器 与七牛源站服务器向我们吐的Etag不同导致的。
Etag/If-None-Match也要配合Cache-Control使用。
l Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器觉得)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
l If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
l Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
l 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存,这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
l 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。