У меня большой проект, и мы решили залить кеш для лака. После многих правок мы внедряем его на рабочий сервер. Все было в порядке, но примерно через 8 часов пользователи стали жаловаться, что они входят в систему под своим адресом электронной почты и попадают в другого пользователя!
Мы решили удалить весь кеш сеанса и перезапустить varnish и nginx, но иногда пользователи продолжают жаловаться.
Итак, вопрос: как лак может сломать сеансы php? Как такая ситуация могла быть?
Конфигурация моего лака:
vcl 4.0;
acl invalidators {
"localhost";
"127.0.0.1";
}
backend modniyostrov {
.host = "example-site.com";
.port = "8080";
}
sub vcl_recv {
if (req.method == "POST") {
return (pass);
}
if (req.url ~ "/administration/?.*" ||
req.url ~ "/app_dev.php/?.*" ||
req.url ~ "/account/?.*" ||
req.url ~ "/cart/?.*" ||
req.url ~ "/currency/?.*" ||
req.url ~ "/login_check/?.*" ||
req.url ~ "/login/?.*"
req.url ~ "/logout/?.*"
) {
return (pass);
}
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(ProductsViewMode|PHPSESSID|currency|APP_REMEMBER_ME|recentViews|mobile)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
}
#all pictures cache by 15 minutes
if (req.url ~ "^.*\.(png|jp[e]?g|gif|swf|css|js|svg)?(\?v=.*)?$") {
unset req.http.Cookie;
# set req.ttl = 900s;
return (hash);
}
#clear all cache content
if (req.method == "PURGE") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
return (purge);
}
#clear by ban system, particulary by taggs; see FOSHttpCacheBundle
if (req.method == "BAN") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
# find
if (req.http.X-Cache-Tags) {
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
+ " && obj.http.content-type ~ " + req.http.X-Content-Type
+ " && obj.http.X-Cache-Tags ~ " + req.http.X-Cache-Tags
);
} else {
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
+ " && obj.http.content-type ~ " + req.http.X-Content-Type
);
}
return (synth(200, "Banned"));
}
# Add a Surrogate-Capability header to announce ESI support.
# set req.http.Surrogate-Capability = "abc=ESI/1.0";
return (hash);
}
sub vcl_hash {
#unset req.http.Cookie;
set req.http.X-Have-To-Hash = ";" + req.http.Cookie;
set req.http.X-Have-To-Hash = regsuball(req.http.X-Have-To-Hash, "; +", ";");
set req.http.X-Have-To-Hash = regsuball(req.http.X-Have-To-Hash, ";(ProductsViewMode|currency|recentViews|mobile)=", "; \1=");
set req.http.X-Have-To-Hash = regsuball(req.http.X-Have-To-Hash, ";[^ ][^;]*", "");
set req.http.X-Have-To-Hash = regsuball(req.http.X-Have-To-Hash, "^[; ]+|[; ]+$", "");
if (req.http.Cookie ~ "APP_REMEMBER_ME") {
set req.http.X-Have-User = "true";
} else {
set req.http.X-Have-User = "false";
}
hash_data(req.url);
hash_data(req.http.host);
hash_data(req.http.X-Have-To-Hash);
hash_data(req.http.X-Have-User);
return (lookup);
}
sub vcl_backend_response {
#for ban some objects
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
if (beresp.http.Cache-Control ~ "private" ||
beresp.http.Cache-Control ~ "no-cache" ||
beresp.http.Cache-Control ~ "no-store"
) {
set beresp.ttl = 1h;
# set beresp.uncacheable = true;
unset beresp.http.Cache-Control;
}
if (beresp.http.X-Url ~ "^.*\.(png|jp[e]?g|gif|swf|css|js|svg)?(\?v=.*)?$") {
set beresp.ttl = 24h;
}
if (beresp.status == 502 || beresp.status == 404 || beresp.http.X-Cache-Debug) {
set beresp.ttl = 0s;
}
return (deliver);
}
# Check for ESI acknowledgement and remove Surrogate-Control header
# if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
# unset beresp.http.Surrogate-Control;
# set beresp.do_esi = true;
# }
#}
sub vcl_deliver {
# if (!resp.http.X-Cache-Debug) {
# Remove ban-lurker friendly custom headers when delivering to client
# unset resp.http.X-Url;
# unset resp.http.X-Host;
# unset resp.http.X-Cache-Tags;
# } else {
if (resp.http.X-Varnish ~ " ") {
set resp.http.X-Cache = "HIT";
# set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
# }
}
Вы сделали содержимое сеанса кешируемым:
if (beresp.http.Cache-Control ~ "private" ||
beresp.http.Cache-Control ~ "no-cache" ||
beresp.http.Cache-Control ~ "no-store"
) {
set beresp.ttl = 1h;
# set beresp.uncacheable = true;
unset beresp.http.Cache-Control;
}
Учитывая, что для вас это не было очевидным, я думаю, что ваша стратегия использования Varnish - неправильное решение.