清漆configuration只caching未login的用户

我有一个由varnish + nginx向前的Ruby on Rails应用程序。 由于大多数网站的内容是静态的,除非你是一个login用户,我想在用户注销时大量使用varnish,而只是在login时caching静态资产。

当用户login时,他们的cookie中会包含cookie'user_credentials',此外,我需要跳过/ login和/ sessions上的caching,以便用户可以首先获得他们的'user_credentials'cookie 。

Rails默认不设置caching友好的caching控制头,但是当用户没有login时,我的应用程序设置了“public,s-max-age = 60”头。Nginx设置为返回'far future'expires头为所有静态资产。

我目前的configuration完全绕过了login时包括静态资产在内的所有内容的caching,并且在注销时返回cachingMISS。 我花了几个小时绕圈,这里是我目前的default.vcl

director rails_director round-robin { { .backend = { .host = "xxx.xxx.xxx.xxx"; .port = "http"; .probe = { .url = "/lbcheck/lbuptest"; .timeout = 0.3 s; .window = 8; .threshold = 3; } } } } sub vcl_recv { if (req.url ~ "^/login") { pipe; } if (req.url ~ "^/sessions") { pipe; } # The regex used here matches the standard rails cache buster urls # eg /images/an-image.png?1234567 if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") { unset req.http.cookie; lookup; } else { if (req.http.cookie ~ "user_credentials") { pipe; } } # Only cache GET and HEAD requests if (req.request != "GET" && req.request != "HEAD") { pipe; } } sub vcl_fetch { if (req.url ~ "^/login") { pass; } if (req.url ~ "^/sessions") { pass; } if (req.http.cookie ~ "user_credentials") { pass; } else { unset req.http.Set-Cookie; } # cache CSS and JS files if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") { unset req.http.Set-Cookie; } if (obj.status >=400 && obj.status <500) { error 404 "File not found"; } if (obj.status >=500 && obj.status <600) { error 503 "File is Temporarily Unavailable"; } } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } } 

好吧,最后我设法解决这个使用下面的VCL文件。 请注意,我添加了几个额外的位,以便在后端死亡时caching过期宽限。

看来我的主要失败是使用unset req.http.Set-Cookie; 当我应该使用未unset obj.http.Set-Cookie;vcl_fetch部分。 (vcl_fetch中的obj和vcl_recv部分中的req )。

 director rails_director round-robin { { .backend = { .host = "xxx.xxx.xxx.xxx"; .port = "http"; .probe = { .url = "/lbcheck/lbuptest"; .timeout = 0.3 s; .window = 8; .threshold = 3; } } } } sub vcl_recv { if (req.backend.healthy) { set req.grace = 30s; } else { set req.grace = 1h; } if (req.url ~ "^/login") { pipe; } if (req.url ~ "^/sessions") { pipe; } if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") { unset req.http.cookie; lookup; } else { if (req.http.cookie ~ "user_credentials") { pipe; } else { unset req.http.cookie; } } # Only cache GET and HEAD requests if (req.request != "GET" && req.request != "HEAD") { pipe; } } sub vcl_fetch { set obj.grace = 1h; if (req.url ~ "^/login") { pass; } if (req.url ~ "^/sessions") { pass; } if (req.http.cookie ~ "user_credentials") { pass; } else { unset obj.http.Set-Cookie; } # cache CSS and JS files if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") { unset obj.http.Set-Cookie; } if (obj.status >=400 && obj.status <500) { error 404 "File not found"; } if (obj.status >=500 && obj.status <600) { error 503 "File is Temporarily Unavailable"; } } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } } 

我不能评论,所以我发布这个答案。

注意:从2.1.0开始,obj。*在vcl_fetch中被称为beresp。*,而obj。*现在是只读的。

这些似乎更好地放在vcl_recv而不是vcl_fetch:

  if (req.url ~ "^/login") { pipe; } if (req.url ~ "^/sessions") { pipe; } 

最后,在你的后端定义中,我会添加

 .max_connections = 32; 

调整到允许nginx / apache创build的乘客后端数量。 如果你不设置这个限制,你应该留意你的乘客全球排队(假设你正在使用乘客)。