nginx 1.3.12 SPDY add_headers bug

Anatoly Mikhailov anatoly at sonru.com
Tue Feb 12 14:55:54 UTC 2013


On Feb 12, 2013, at 11:28 AM, Maxim Dounin <mdounin at mdounin.ru> wrote:

> Hello!
> 
> On Tue, Feb 12, 2013 at 08:42:06AM +0000, Anatoly Mikhailov wrote:
> 
> [...]
> 
>> Мы отключили 2 из 3х возможных валидатора кэша, так как 
>> Conditional Get применяется в основном для динамического 
>> контента (Cache-Control отключен), там связка ETag+LastModified 
>> (плюс реверс-прокси) - это очень хорошее и надежное решение для 
>> разгрузки сервера. Используя эти заголовки, в одном случае 
>> контент отдается сервером, а клиент берет из 304, в другом - 
>> реверс-прокси отдает одинаковый ответ из своего кэша при 
>> нескольких запросах к серверу, не обращаясь к нему 
>> непосредственно. Манипуляция этими заголовками на сервере дает 
>> большую свободу для кэширования. Но все это, разумеется, с 
>> отключенным Cache-Control. Статика же, наоборот, постоянный 
>> статичный контент.
>> 
>> В данном случае речь идет о третьем возможном валидаторе - 
>> статике с Cache-Control public, который смотрит на имя файла и 
>> отдает его из кэша с 304, если такой был уже загружен.  Убрав 
>> заголовки для статики, мы попытались облегчить браузеру 
>> необходимость проверки на Conditional Get и генерации md5 (Etag) 
>> каждый раз для статичных файлов. В том вслучае если статика 
>> изменяется при деплое мы переименовываем файлы по принципу 
>> all.js?timestamp
>> 
>> Поправьте, если я что-то не понимаю.
> 
> Давайте начнём с базовых понятий.  Когда у нас есть ответ из кеша, 
> то прежде чем его использовать, нужно
> 
> 1) Убедиться, что ответ свежий (fresh, not expired), и если да - 
> то ответ можно использовать (замечу - 304 тут ни при чём, см. 
> ниже).  На этот этап, в частности, можно влиять с помощью 
> заголовков Expires и Cache-Control max-age.  (Но вообще следует 
> иметь ввиду, что на этом этапе браузеры используют довольно много 
> эвристики, и заставить их считать ответ свежим - в общем случае 
> невозможно.)
> 
> Подробнее тут:
> http://tools.ietf.org/html/rfc2616#section-13.2
> 
> 2) Если ответ не свежий, то проверить его (валидировать) с помощью 
> запроса к серверу.  В этом месте используются cache validator'ы, 
> которых в HTTP определено два, Last-Modified и ETag.  Тут и только 
> тут может появится 304-й ответ (если ресурс на сервере не менялся, 
> и cache validator совпадает).
> 
> Подробнее тут:
> http://tools.ietf.org/html/rfc2616#section-13.3
> 
> Использование Cache-Control public - вообще говоря на 
> вышеописанные механизмы никак не должен влиять.  Это специальный  
> параметр, позволяющий сказать кешам по дороге, что данный 
> конкретный ответ - годен для всех пользователей, даже если для 
> доступа к ресурсу использовалась авторизация.  (Я допускаю, что 
> некоторые браузеры могут учитывать его при определении свежести 
> ответа, но это лишь детали эвристики.)
> 
> Подробнее про Cache-Control public тут:
> http://tools.ietf.org/html/rfc2616#section-14.9.1
> 
> Конфиг, который у вас написан, исключает использование механизма 
> из пункта (2), и оставляет браузер перед выбором в пункте (1) - 
> счесть ответ свежим, или идти на сервер за новым ответом.  AFAIK, 
> упомянутые механизмы в браузерах никак не связаны, и запрет 
> использования механизма ревалидации - только ухудшает 
> ситуацию, никак не влияя на принятие решения о свежести.
> 
> -- 
> Maxim Dounin
> http://nginx.com/support.html
> 
> _______________________________________________
> nginx-ru mailing list
> nginx-ru at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-ru


Максим, спасибо за развернутый ответ, это проясняет некоторые вещи о кэшировании в целом.
Но вернемся к статике без E-Tags и Last-Modified.  Предполагаю, что эвристика разных браузеров 
для "expires max; add_header Cache-Control public;" схожа, так как этот конфиг в продакшне
уже более года. Статика всегда кэшировалась на клиенте и по пути, где успевала оседать на прокси.

Эмпирическим путем мы выяснили, что 'Cache-Control public' все браузеры воспринимают одинаково
и, более того, бонусом кэшируют статику для SSL-соединения, которая, в противном случае, очищается 
из браузерного кэша (и на промежуточных прокси) без данного заголовка.
Все тестирование, которое мы проводили никак не привело к ухудшению ситуации, все браузеры
вели себя, может не по спецификации, но предсказуемо.

Сейчас включил логи и протестировал с Last-Modified/E-Tag и без них. В данном конкретном случае
это не повлияло на результат. Сейчас более подробно.

У нас стейджинг сервер с самоподписанным SSL сертификатом, на нем Nginx 1.3.12 + SPDY.
На продакшне, разумеется, валидный SSL сертификат с Nginx 1.3.5 + SPDY 50, если не ошибаюсь.
На продакшн серверах вся статика кэшируется в браузерах и на сервер запросы не идут.

На стейджинге Firefox все берет из своего кэша, не обращаясь на сервер (наличие E-Tags/Last-Modified не влияет),
но Chrome на стейджинге постоянно идет на сервер за статикой, тут не влияет наличие этих заголовков.
Вопрос - может ли невалидный сертификат повлиять на это? 
"

Анатолий


Подробная информация о списке рассылки nginx-ru