Cache revalidation using If-None-Match

Gena Makhomed gmm at csdoc.com
Fri Jul 18 11:14:45 UTC 2014


On 18.07.2014 1:23, S.A.N wrote:

>> Причина в бекенде, да. Но переписать весь софт "правильно"
>> - не хватит времени и сил. Например, вот та же MediaWiki.
>
> Кстати MediaWiki, использует переменую $_SERVER['HTTP_HOST'] без всякой
> проверки.
> Если вы используете MediaWiki, советую поискать в коде $_SERVER['HTTP_HOST']
> и изучить степень угрозы.

В качестве workaround`а я обычно использую двойное проксирование,
nginx -> nginx -> php-fpm, так что nginx в результате сам исправляет
этот глюк с HTTP_HOST, на все невалидные запросы отвечая 400 статусом.

Правда, чтобы он вел себя в полном соответсвии с требованиями RFC:

http://tools.ietf.org/html/rfc2616#section-5.2

If the host as determined by rule 1 or 2 is not a valid host on
the server, the response MUST be a 400 (Bad Request) error message.

- его приходится специально настраивать для этого,
"из коробки" он с требованиями RFC не совместим.

>> Если все делать на бекенде - тогда вам nginx просто не нужен.
>
> У нас изначально РНР фрейворк проектировался как REST приложения, в нем
> очень приятно реализовывать логику на уровне HTTP.
>
> По этому мне привычней и удобней это делать имино на бекенде.
> Наверно ваше мнения было таким же, если вместо MediaWiki, вы использовали
> что-то более подходящее на роль REST приложения.

MediaWiki приходится использовать, потому что это на сегодня есть
наиболее удобный для пользователя движок wiki, - killer app и все такое.

> Я ничего не имею против MediaWiki но именно из-за таких фрейморков удобней
> что-то дописать в конфиге вебсервера, вместо реализации этой логики на
> уровне HTTP протокола, в самом приложении, что дает возможность понимать
> вашу логику приложения, всем кто понимает HTTP заголовки.

Таких приложений, как MediaWiki - подавляющее большинство на сегодня.
Например, WordPress не далеко ушел в этом плане от MediaWiki:

http://codex.wordpress.org/Nginx
http://wiki.nginx.org/WordPress

>> Оптимальный вариант - это все-таки делать на стороне nginx то, что
>> он умеет делать лучше всего (SSL, gzip, кеширование, отдача статики)
>> а на стороне backend`а - только генерирование контента для динамики.
>
> Мы со временем пришли к тому что и контент сжимаем в gzip, сразу на
> бекенде.
> Если есть Nginx кеширования, такая схема работает намного эффективней.
> Папка кеша занимает меньше места, считывания происходит быстрей, Nginx не
> тратит проц время на сжатия.

да и SSD изнашивается не так быстро, если кеш nginx размещен на SSD.

> Главное не забыть включить gunzip, он нужен для клиентов которые не понимают
> gzip, для них Nginx отдаст несжатый ответ, таких клиентов мало, 10% - 15%.
>
> Таким образом мы один раз сжали ответ на бекенде, потеряли там 2-5ms
> времени, но Nginx будет сотни раз отдавать этот ответ из своего кеша, таким
> образом мы сэкономили в сотни раз больше процессорного времени и в несколько
> раз сэкономили место на диске под файл кеша.

Да, прекрасно понимаю. Для этих/похожих целей в nginx
есть ngx_http_gzip_static_module и ngx_http_gunzip_module.

Хотя имхо идеальным вариантом было бы все-таки, если бы nginx
сам умел сжимать ответ от backend`а перед помещением его в свой кеш.

> Даже моё желания написать статью про ревалидацию кеша через ETag, и отдать
> ответ c 304 статусе и уложится за 5ms, мои колеги встретили неоднозначно,
> некоторые даже посчитали что это нарушает их автор право, но принципиально
> особо никто не против.

Всеравно nginx отдаст 304 ответ из своего кеша еще быстрее,
чем веб-приложение на которое он проксирует запросы клиентов.

> <?php
>
> $base = new EventBase();
> $http = new EventHttp($base);
>
> $http->bind('0.0.0.0', 8080);
> $http->setDefaultCallback('App\responseHTTP');	
>
> $base->loop();
>
> ?>
>
> Ваша функция App\responseHTTP, принимает объект request и отдает через него
> заголовки и тело ответа.
> Скрипт работает в одном потоке, Libevent сам держит пул конектов и асинхроно
> отвечает.
> РНР просто синхроно, обрабатывает запросы один за другим, на один простой
> запрос уходит 2-7 ms.
> Очень советую, надеюсь РНР будет развиватся в этом направлении, и когда-то
> мы получим ApplicationServer из коробки, который будет работать
> действительно на FastCGI модели.

У этого подхода есть и минусы. Утечки памяти будут накапливаться,
и малейшая ошибка в коде будет приводить к краху всего веб-сервера.
По этим граблям народ уже основательно прошелся, используя node.js
Да и со сборкой мусора у PHP не очень хорошо, по сравнению с Java.

Если уж использовать такую модель - имхо лучше это делать на Java
или другом языке, который запускается поверх JVM. В других языках
(интерпретаторах/компиляторах) сейчас только пытаются повторить то,
что было в Java сделано уже 10-15 лет тому назад и отлично работает.

Да и язык программирования Java сам по себе - просто отличный язык,
не смотря на некоторые небольшие недостатки в библиотеках и синтаксисе.

-- 
Best regards,
  Gena



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