У нас возникла проблема с настройкой, когда Varnish начал выдавать пустые страницы. Мы завершаем ssl перед лаком и используем установку apache2.4 + php-fpm поверх fcgi за ним.
На первый взгляд казалось, что страницы находятся только в устаревшем приложении, в котором мы обречены использовать php5.6, поэтому мы можем получить белые страницы гибели. Но эти ошибки случались случайно. Также были затронуты приложения php7.2.
Следующие предположения касались недавних изменений в apache с нашей стороны (тип мьютекса). Это тоже оказалось неправильным.
Включение кеширования решило проблему, но не решило ее.
Все поиски в Интернете намекали на корреляцию между Content-Encoding: chunked и неправильной версией http, но, проверяя это, мы используем http / 1.1 до и после лака. Также у нас возникла эта проблема случайно (~ 0,6% страниц).
(Я пишу это как вопрос, на который я сам отвечу, чтобы следующая бедняжка сразилась с этой странностью. И почему-то это никогда раньше не подвергалось сомнению ...)
Решение пришло ко мне во время тестирования:
Я тестировал на нескольких машинах, используя curl и менее. Но иногда я использовал -I
, таким образом инициируя запрос HEAD. Оказалось, что запрос HEAD обрабатывается как запрос GET с точки зрения кеширования (тот же ключ кеша), но серверная часть просто отвечает без тела на запросы заголовка. Таким образом, вы получаете кеш-объекты без тела, которые также запускают HIT для запросов GET.
Я просто добавил эту строку в vcl_hash, и проблема исчезла:
hash_data(req.method); // cache HEAD requests seperately
надеюсь, что это поможет кому-то еще пропустить 2 недели отладки.
HEAD
ЗапросыПоведение Varnish по умолчанию - принять HEAD
запрос и превратить его в GET
запрос.
Ответ сохраняется в кеше, но полезная нагрузка удаляется перед возвратом клиенту.
Это сделано намеренно из соображений эффективности и не нарушает RFC. Вывод должен быть идентичным.
Varnish не добавляет вариант кеширования на основе метода запроса. Так как HEAD
превращается в GET
, это изменение не требуется.
В вашем конкретном случае вы выполнили оптимизацию на уровне источника для обработки HEAD
Запросы. По-видимому, получение чистого и неподдельного HEAD
запросы на происхождение имеет значение.
Чтобы добиться этого и обойти поведение по умолчанию, есть 2 распространенных способа:
Вы можете явно установить метод запроса на HEAD
в vcl_backend_fetch
:
sub vcl_recv {
set req.http.method = req.method;
}
sub vcl_hash {
hash_data(req.http.method);
}
sub vcl_backend_fetch {
if(bereq.http.method == "HEAD") {
set bereq.method = "GET";
}
unset bereq.http.method;
}
Вы можете обойти кеш:
sub vcl_recv {
if(req.method == "HEAD") {
return(pass);
}
}
Первое решение в вашем случае, вероятно, лучше второго.
Хотя вы утверждаете, что нет логики VCL, которая удерживает HEAD
запросы нетронутые, я подозреваю, что что-то происходит в вашем VCL.
Я хотел бы увидеть ваш полный файл VCL и попробовать его сам. Не стесняйтесь редактировать любые конфиденциальные данные.
Хотя мне трудно поверить, что ваша установка Varnish сохраняет HEAD
запросы без каких-либо специальных VCL, то решение, которое вы предлагаете, является действительным.
Создание варианта кеша для каждого метода запроса - хороший способ решить вашу проблему.
Независимо от того, есть ли у вас специальный VCL для HEAD
запросов, это поведение, которое вам нужно, чтобы удовлетворить ваш исходный сервер. Я не собираюсь с этим спорить.
Единственная причина, по которой я занимаюсь этой темой, - это то, что мне интересно, что вызвало эту проблему. Вы уже предоставили решение, я просто хочу убедиться, что мы оба понимаем, почему все произошло именно так.
С нетерпением жду этого файла VCL и спасибо за ваш вклад.