我们在一堆 IIS 服务器前面安装了 Varnish 3.0.6。
IIS 服务器不关心传入请求的大小写,尽管我不断提醒开发人员,但他们当然在所有代码中使用 RandomCase。我以为这会导致最糟糕的结果就是缓存中的资源重复,然而我们看到的是 Varnish 在某些情况下根本不缓存。
我有一个网址,例如http://www.example.com/Content/images/flags/gb.png。
我在 VCL 中设置了一个标头,以告诉我该请求在 Varnish 中是命中还是未命中,如果我curl
从某处使用该标头几次命中,我就会得到我期望的命中:
$ curl -Ss -X GET 'http://10.0.0.1/Content/images/flags/gb.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: HIT 15 Var01
但是,如果我使用的 URL 的大小写不正确,无论我获取多少次,都会得到 MISS 的结果:
$ curl -Ss -X GET 'http://10.0.0.1/content/images/flags/gb.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: MISS Var01
奇怪的是,如果文件名和路径是错误的,是缓存:
$ curl -Ss -X GET 'http://10.0.0.1/content/images/flags/GB.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: HIT 15 Var01
因此看起来,如果路径和文件都正确,或者都不正确,它就会被缓存,但如果一个正确,一个不正确,它就会被缓存,绝不已缓存。
$curl -Ss -X GET 'http://10.0.0.1/content/images/flags/gb.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: MISS Var01
$curl -Ss -X GET 'http://10.0.0.1/content/images/flags/GB.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: HIT 7 Var01
$curl -Ss -X GET 'http://10.0.0.1/Content/images/flags/gb.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: HIT 7 Var01
$curl -Ss -X GET 'http://10.0.0.1/Content/images/flags/GB.png' --header 'Host: www.example.com' -I | grep X-Cache
X-Cache: MISS Var01
varnishlog
以下是“缺失”请求的输出示例:
168 SessionOpen c 192.168.0.1 60412 :80
168 ReqStart c 192.168.0.1 60412 96071146
168 RxRequest c GET
168 RxURL c /content/images/flags/gb.png
168 RxProtocol c HTTP/1.1
168 RxHeader c User-Agent: curl/7.35.0
168 RxHeader c Accept: */*
168 RxHeader c Host: www.example.com
168 RxHeader c X-Forwarded-Proto: https
168 VCL_call c recv
168 VCL_return c lookup
168 VCL_call c hash
168 Hash c /content/images/flags/gb.png
168 Hash c www.example.com
168 VCL_return c hash
168 HitPass c 95565251
168 VCL_call c pass pass
168 Backend c 236 my_director web08
168 TTL c 96071146 RFC 120 -1 -1 1462797933 0 1462797954 0 0
168 VCL_call c fetch
168 TTL c 96071146 VCL 28800 -1 -1 1462797933 -0
168 VCL_return c deliver
168 ObjProtocol c HTTP/1.1
168 ObjResponse c OK
168 ObjHeader c Content-Type: image/png
168 ObjHeader c Last-Modified: Wed, 04 May 2016 07:56:47 GMT
168 ObjHeader c Accept-Ranges: bytes
168 ObjHeader c ETag: "809d381daa5d11:0"
168 ObjHeader c Server: Microsoft-IIS/8.5
168 ObjHeader c X-Powered-By: ASP.NET
168 ObjHeader c Date: Mon, 09 May 2016 12:45:54 GMT
168 ObjHeader c Content-Length: 599
168 ObjHeader c X-Backend: web08
168 VCL_call c deliver
168 VCL_return c deliver
168 TxProtocol c HTTP/1.1
168 TxStatus c 200
168 TxResponse c OK
168 TxHeader c Content-Type: image/png
168 TxHeader c Last-Modified: Wed, 04 May 2016 07:56:47 GMT
168 TxHeader c Accept-Ranges: bytes
168 TxHeader c ETag: "809d381daa5d11:0"
168 TxHeader c X-Backend: web08
168 TxHeader c Content-Length: 599
168 TxHeader c Accept-Ranges: bytes
168 TxHeader c Date: Mon, 09 May 2016 12:45:32 GMT
168 TxHeader c Age: 0
168 TxHeader c Connection: keep-alive
168 TxHeader c X-Cache: MISS Var01
168 Length c 599
168 ReqEnd c 96071146 1462797932.596346378 1462797932.619358778 0.000039339 0.022963524 0.000048876
更新:更令人困惑的是,我们在这里运行的另一个网站(也是基于 IIS 的)没有出现此问题,所以我怀疑有些奇怪的事情发生了,但我不知道在哪里。我看不出 Varnish 可能看到了什么,让它认为这些请求是 MISSes - 它看到的只是 URL,因为我的vcl_hash
只是hash_data(req.url);hash_data(req.http.host)
答案1
如果 Varnish 后面的所有服务器都是 IIS,那么以下内容应该可以帮助您解决此问题。
import std;
...
sub vcl_recv {
set req.url = regsub(req.url, "\?.*", "");
...
}
...
这样,您就不必在每个表达式中使用 (?i) 进行正则表达式不区分大小写的匹配。