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