Как стать автором
Обновить

Комментарии 17

Можно было бы вместо добавления редиса ванильным нджинксом кешировать, а на стороне бекенда менять етаг и обновлять кеш простым нттр запросом в нджинкс. Чем топорней решение, тем меньше точек на отказ.

Погуглил. Это похоже кэш на стороне клиента, верно?

Я здесь кэш на стороне сервера.

Т.е. единожды отрендеренный ответ отобразится всем разным пользователям.

Т.е. с Етаг 10000 разных пользователей заставят отработать веб-приложение (PHP) 10000 раз. А с кэшем через nginx + redis - 1 раз.

А потом мы получаем нерабочие страницы сайтов, потому что оказывается, что проблема валидации кеша - это ого-го какая проблема на самом деле.

У etag я пока не понял как сбрасывать, да и много вопросов, как оно повлияет при сотен тысяч страниц... можно ли кэш прогревать, массово сбрасывать, сбрасывать по событию.

Если речь о моём решении, то кэш на 100% управляется из приложения, этих проблем нет.

можно ли кэш прогревать, массово сбрасывать, сбрасывать по событию.

  1. Кеш можно прогревать. Для прогрева необходимо отправить запрос на нджинкс, если страниц много это займёт время.

  2. Можно сбрасывать весь кеш. Просто удалить папку с кешом сбросит его.

  3. Сброс по событию возможен. В случае наступления события необходимо отправить HTTP запрос на нджинкс с заголовком if-modified-since.

Для кого проблема, для кого задача)

Не верно конечно, кеш находится на стороне клиента И на стороне нджинкса.

А есть ссылочка, где подробнее почитать о настойке и управлении из веб приложения?

Я правильно понимаю, что так можно?

  1. etag нужно генерировать на стороне PHP

  2. связать etag с конкретным url

  3. передать его как-то(в хедере?) в nginx вместе с ответом

  4. При изменении сущности проверять какие etag зацепило изменения и как-то(как?) сбрасывать его на стороне nginx

с ходу я такое не нагуглил. Перебрали десяток nginx админов на upwork со ставкой до 150 в час, никто такого решения не предложил.

Если реально так можно, прошу поделиться мануалами.

UPDATE:

Ещё интересно, а что если клиент придёт с другим etag? (должна отдаться кэш страница)

А как прогреть этот кэш, если нужно будет?

А как оно работает с сотнями, миллионами страниц?

Тема с кешированием очень обширна и конкретно под ваш случай готовый ответ будет выполнением всей работы самостоятельно. Вот близкое объяснение.

Основываясь на том, что я нагуглил по теме Etag, он не решает вопросы, которые описаны в статье, он не гибкий, проблемы с валидацией.

  1. В кэше сотни тысяч страниц

  2. Как я понял при Etag кэшировании, для валидации кэша Nginx должен обращаться к веб-приложению. Это значит

    1. либо через redis делать на стороне nginx как-то

    2. либо запускать каждый раз веб-приложение для валидации

    3. либо каждому клиенту заново рендерить страницу (а миллионы клиентов уникальны)

  3. Определённые страницы должны сбрасывать по условиям изменения сущностей (управление из бэкэнда) - проблема валидации Etag опять же

  4. Как оно поведёт себя при сотнях тысяч страниц

  5. Как прогреть этот кэш (вобще не возможно видимо)

  6. Если клиент придёт без Etag или изменит его. Кэш не отработает как я понял

Вобщем Etag это простое решение, для максимально простых и не требующих надёжности целей.

А чтоб настроить Etag для такого-же функционала, как lua+redis, нужно намного больше времени и намного более высокая квалификация nginx админа. Следовательно выше порог вхождения и дороже поддержка.

Именно эти все проблемы решаются моим рецептом :)

Не знаю как вы пришли к такому выводу, но рейтинг статьи всё показывает. Успехов вам в ваших задачах.

Благодарю. По вашему варианту хороший нашёл мануал тут, может пригодится кому-то, для альтернативного варианта:) Если ещё люди положительно выскажутся за Etag добавлю в конце статьи апдейт.

https://symfony.ru/doc/current/http_cache/validation.html

нужно много тестировать. Тот же сброс, время прогрева, обновление по http request.

Кстати, а считать статистику посещений страниц при Etag как-то можно через nginx?

И да, возможно писать статьи не моё, для того рейтинг и есть:)

Кмк, Etag можно использовать не вместо, а вместе с вашим решением, чтобы экономить не время, а трафик.

Т.е. в месте (вместо) ngx.print(res) добавляем логику:

— Вычисляем значение ETag для содержимого виджета

— Если от клиента пришел заголовок If-Match и он совпадает с ETag текущего отдаваемого контента - просто вернуть "304 Not Modified".

— Если контент отличается - отдать тело и новый ETag

Т.о. если виджеты объемные и показываются пользователю более одного раза за сессию - фактически отдаваться они будет единожды (до тех пор пока не изменятся в Redis)

Ну а дальше можно поиграться с хранением горячих ETag в LUA LRU табличке, чтобы на этот раз снизить нагрузку на Redis, но только на короткий срок или имея какую-то % вероятность пробива в Redis, чтобы удостовериться что данные там не изменились. (Либо заставить ваш flushRelatedCache отправлять специальный запрос в специальный location nginx, чтобы реализовать логику подчистки таблицы)

если виджеты объемные и показываются пользователю более одного раза за сессию

В среднем 1.5 раза за сессию.

Мне очень нравится ваш вариант, это снизит траффик на 33%

Можно вместе, можно вместо. Я имел ввиду хранение кеша не в редисе, а в нджинксе. Как это работает с редисом:

  1. В случае события сброса, мы вызываем генерацию новой страницы.

  1. Помещаем запросом в редис содержимое.

Как это работает с нджинкс:

  1. Делаем запрос в нджинкс для сброса кеша.

  2. Делаем запрос в нджинкс для сохранения новой страницы в кеше.

Ага, давно не общался с nginx настолько плотно, так что навертел логику ETag руками)

proxy_store и unlink решает проблемы без openresty. Плюс кэш можно в оперативную память смонтировать

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории