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

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

Есть еще Varnish, не пробывали его?
Я не пробовал, но было бы интересно услышать отзывы или сравнение SSI+кеш от Сысоева и Varnish как прослойка между nginx и becken-ом.
Спасибо за ссылки.

В первой статье производительность будет падать за счет того что для работы с Memcached потребуется сетевые операции.

во второй статье мы получим скорее всего сравнимую производительность nginx-кешом.
Имею мнение, что рациональнее заходить с другой стороны — встраивать через ssi отдельные блоки, и кэшировать каждый блок по отдельности. Это позволяет более гибко работать с временем кэширования, и избавиться от костыля с пуржингом кэша.
IMHO, это самый прозрачный способ.
Я с Вами согласен. В данном случае каждый блок кешируется именно по отдельности, сборка блоков в готовую страницу происходит при каждом запросе к серверу. Просто алгоритм сборки настолько заоптимизирован, что этот процес отъедает очень малую долю процессорного времени.
Если fastcgi_cache написал на весь location / {} — где ж тут по-отдельности?

Возможно вы не привыкли к стилю конфтгов nginx, в данном конкретном случае в кеш не попадает «по умолчанию» ничего, т.к. время кеширования равно 0.

По какому принципу ложить в кеш указано в директиве fastcgi_cache_key $uri$is_args$args; Т.е., например, сранички /menu.php и /menu.php?key=value будут размещены в разных кеш-файлах.

Кроме того в кеше не происходит подмены ssi-инструкций. Если в index.php есть "", то в кеше эта инструкция так и остается. Подмена происходит в менент запроса и если menu.php нету сейчас в кеше то происходит обращение к бекенду и размещение в кеш только menu.php, где время размещения в кеше определяется по заголовку «Cache-control».

Объяснил как умел, если неумело, то настройте локальную копию и убедитесь в этом сами.

А очистка кеша нужна для того что указана инструкция fastcgi_cache_use_stale, если ваш бекенд сгенерит ошибку то она не будет показана, абудет взята устаревшая копия с кеша. Ну если устаревшей копии в кеше нет, только тогда можно увидеть сбой.

Но если запрашивается сраничка index.php, menu.php,… то в кеше создается отдельная страничка
Там хабракат кое-что вырезал, в скобочках было <!--# include virtual=«menu.php» -->
Мама, роди меня обратно…

Я как бы так помягче сказать, использую nginx в продакшне уже года четыре. Примерно на 800-та серверах. Зачастую, с собственными патчами. С трафиком в пределе около 30к rps на nginx.
Но это так, к слову.

Собственно, я хотел обратить внимание на то, что существенно дешевле не делать кэш для всего с нулевым таймаутом, а кэшировать только те куски, которые вставляются через ssi. Чтобы не строить кэш-кэй по целой простыне параметров. Чтобы не городить огород с use_stale.

Это позволит также избавиться от «если ваш бекенд сгенерит ошибку». Можно перехватить ошибку бэкэнда для каждого отдельного блока.

Я с Вами согласен что схему можно селать более оптимальной, но согласитесь что при этом конфиг будет выглядеть сложнее для понимания схемы.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Можно поидее ж примонтировать часть ОП как папку Ж…
НЛО прилетело и опубликовало эту надпись здесь
Структура старницы
Збойный блок
Поправьте, глаза режет.
«движек» туда же
Че за херня? Тема: Кеширование блоков с помощью nginx, а в статье уже рассказывается как его заинсталить и как заинсталить РНР, че за бред?

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

А если видите что-то лишнее для себя, переходите с следующему подзаголовку.

Поправьте, бога ради, окончания «тся» и «ться».
Не рассматривали ли вы такой случай, когда сайт реализован на каком-то относительно тяжелом фреймворке (для которого время «разогрева» сравнимо или даже превышает время создания содержимого блока), и при этом страница содержит более одного блока с нулевым или близким к нулю временем жизни? Получается, что может возникнуть ситуация, когда время двух запросов к бэкенду за содержимым некэшируемых блоков превысит время создания всей страницы без использования кэша.
В любом деле нужно действовать без фанатизма. Я с Вами согласен, что в таком случае все переводить на блоки нельзя.

Вобще-то можно, частично, неужели все блоки должны быть актуальны? Посто каркас страницы кешировать уже не получится, а вот ленту новостей, курсы валют, блок с счетчиками/информерами,… можно поробовать.
Способ слишком не гибкий — применяли уже кое-что подобное.
Почему? Потому что могут быть принципиально не кэшируемые блочки: те что зависят от текущего пользователя, например, «Спасибо, что заглянули, %username%! У вас %msg_count% новых сообщений». Каждый такой блочок будет выражаться в запросе к backend-у. Допустим таких блочков у нас 5 (вполне возможная ситуация: приветствия, формы, контролы над своими сообщениями и т.п.), это означает, что на каждую страницу на нужно делать 5 запросов к backend-у, пусть все они будут простыми, но с каждого мы получим оверхед сети, fastcgi запроса/разбора, проверки текущего пользователя. В общем, ужасно.

Куда эффективнее да ещё и гибче разруливать такие вещи на самом backend-е
почитайте доки по nginx ssi. там есть поддержка переменных и выражения. так что при должном старании, можно и это сделать. я так понял, автор хотел только поверхностно ознакомить с темой поэтому и не рассмотрел этот аспект.
Причём тут поддержка переменных и выражения?
Мне нужно прочитать сессию пользователя из, скажем, редиса, запросить сколько у него сообщений ещё откуда-нибудь (PostgreSQL) и вывести соответствующую фразу. ngnix же это за меня не сделает?
Или, например, мы показываем список постов, для текущего пользователя нужно показать кнопки редактирования рядом с его постами, что же мне кэшировать этот список постов отдельно для каждого юзера?
Вверху страницы делается одна ssi-вставка типа /usersettings/, которая кешируется по сессионной куке uid.
Эта вставка выдет список из set var с id постов (последних N постов) юзера (и любых других его данных).
Ниже, при выводе списка для каждого поста с помошью ssi if проверяем существование переменной с id поста среди списка постов юзера. Внутри каждого if — кнопка.

И не забываем про internal для локейшена /usersettings/ и параметр wait для его вставки.
Еще можно для него указать таймаут в несколько секунд, чтобы все хоть как-то работало, когда база сдохнет.
получаем сессию отдельным блоком, на результат накладываем xslt, который раскидает данные сессии по документу.
Во-первых, это гемор, во-вторых xslt — это не так уж быстро, в третьих остаются блочки некэшируемые по другим причинам: число сообщений у юзера, статус онлайн кого-нибудь, просто часто обновляющаяся инфа, в-четвёртых, libxml/libxslt текут, в-пятых, чтобы делать xsl-трансформацию нужно чтобы ssi-скрипты выдавали валидный xml.

Ну и в конце концов, что у нас получится? Бекэнд со своим движком и какими-то шаблонами (предположительно), ssi-шаблончики, xsl-трансформации. жуткий зоопарк.
1. это ни разу не гемор. гемор — это писать тучи сси-ифов
2. и не так уж и медленно.
3. какая разница по каким причинам они не кэшируются?
4. откуда такие данные? это ведь не какие-то левые пропиетарные библиотеки.
5. это так сложно выдавать валидный xml?

а зачем нам «какие-то шаблоны», если мы всё-равно накладываем xslt? ;-) пусть движок отдаёт чистый xml, ssi объединяет несколько xml-ек в одну и xslt приводит это дело к удобочитаемому виду. кстати, nginx случайно не поддерживает xi:include?
1. SSI + XSLT + шаблоны в бэкенде (без последних если используем только xslt) шаблоны двух видов — гемор. xslt сам по себе не самый удобный шаблонизатор.
3. Такая разница, что если блок не кэшируется принципиально, то придётся запрашивать его с бекэнда каждый раз, и если таких блоков больше одного, то вся эта солянка теряет смысл. И даже если один, она становится очень сомнительной.
4. Тестировали, некоторые трансформации текут. Возможно, если просто подсовывать значения, то с этим не столкнёшься.
5. Намного сложнее, чем html, любой неэкранированный символ, любая неопредённая entity, неправильный utf символ и всё, весь документ сломался.
1. уж по удобней, чем большинство
3. одним запросом можно получить все некэшируемые блоки
4. багрепорт конечно же не написали?
5. любой баг вылезает сразу, а не когда его найдёт кулхацкер. это плохо?
1. Не используйте большинство, используйте удобный.
3. Почему тогда просто не посчитать эти блоки на бекэнде всунуть их в страницу точно также как нгинкс, подтянуть что-то из кеша, тоже всунуть и выдать страницу?
4. Я писал другой багрепорт для libxslt раньше, понял, что всем похуй.
5. Не сразу, а когда возникнет такая ситуация, и в такой ситуации у тебя тупо перестанет отображаться вся страница.
1. это о чём речь?
3. идея сабжа как раз и заключается в том, чтобы не изобретать велосипед, а воспользоваться кэшированием энжиникса.
4. м… печальненько.
5. лучше ничего не показать, чем показать xss
1. Выбирайте на свой вкус, мне, например, нравится jinja2.
3. Если уж говорить о велосипедах, то скорее идея сабжа «а вот есть ещё такой быстрый велосипед». Но есть, то и дургие, ничего изобретать не надо.
5. Да там нет никакой xss, данные могут и не от пользователей браться, в конце концов. Просто если заворачивать данные в xml простой конкатенацией строк, то неизбежно будешь ловить такие баги время от времени, а как-то хитрее уже медленнее. Вообще, необходимость все данные заворачивать в xml не особо удобна.

Я не говорю же, что такой подход нельзя использовать, я говорю, что он негибкий, а значит для каких-то типов сайтов будет неэффективен, неудобен и/или порождать кучу извращений, чтобы втиснутся в рамки.
1. бугога х))) спасибо, такого мне не надо
3. но тогда у нас не получится map-reduce архитектуры
5. не надо заворачивать данные в xml конкатенацией строк. это вредная привычка. и именно благодаря ей xss и просачивается.
3. Захочешь — получиться, не захочешь — сделаешь такую какую захочешь.
5. Чем-то приходиться жертвовать ради скорости, чтобы не было xss достаточно проверять данные на входе.
5. ага, типа как на хабре — каверкать любое упоминание слова javascript? x)
Кстати, вопрос на засыпку. Вы сами-то использовали такое кэширование с ssi?
нет
Ну вот, а я гавна такого сорта уже поел, и xslt тоже.
у тебя нет вкуса
Ты даже не понял смысла моей фразы, и при этом ещё бросаешь безосновательные ощущения.
я прекрасно всё понял.
простите за глупый вопрос. а как нгикс понимает что див кешировать, а не Спан? можно для примеру кусок пхп кода, чтоб понять как страница на пхп выглядит.
nginx парсит SSI-инструкции, ему неважно какой кусок html вы упаковали в блок. В статье есть ссылка на исходный код linux.ria.ua/SsiBlocks/. Если в коде не разберетесь пишите.
Все врубил.
я однажды от скуки померял сайт на ssi, лежащий на локалхасте, утилитой ab и обнаружил, что медленнее Server Side Includes что-то еще поискать надо! как я понял, он при каждом инклюде форкает новый процесс апача/nginx, а эта операция в юниксе чрезвычайно затратная и по времени, и по памяти
Только что проверил сабж (ваш пример, который, как я понял, особо ничего и не делает) и свой собственный сайт, на тяжелом движке с большим количеством запросов к базе, к тому же на хостинге в другой стране, — так и есть:

ваш сайт
HTML transferred: 3109309 bytes
Requests per second: 143.95 [#/sec] (mean)
Time per request: 69.468 [ms] (mean)
Time per request: 6.947 [ms] (mean, across all concurrent requests)
Transfer rate: 462.66 [Kbytes/sec] received

мой
HTML transferred: 24322000 bytes
Requests per second: 226.20 [#/sec] (mean)
Time per request: 44.209 [ms] (mean)
Time per request: 4.421 [ms] (mean, across all concurrent requests)
Transfer rate: 5452.79 [Kbytes/sec] received
Я думаю твой тест может претендовать на звание «самый объективный тест в рунете», тут даже нету смысла говорить о чистоте эксперимента — результат очевиден. Ура!
Наркоман штоле?
nginx новый процесс не форкает.
Тем не менее, результаты удручающие.
сравнение не корректное, приложения работают в разных окружениях.
Я бы согласился с вами, если б не огромная разница в Transfer rate.
Я тут протестил, оказывается хабр работает намного медленее, чем мой собственный сайт-визитка в локалке :)
Я кажется написал, что сайт находится в другой стране, а не в локалке, ок?
Да, и это полностью сводит на нет всю объективность вашего измерения…
при каждом инклюде форкает новый процесс апача/nginx

nginx устроен по другому
не всегда в случае сбоя нужно показывает кэшированную версию. зачастую требуется заглушка или хотябы ремарка о том, что эти данные могут быть не актуальны…

а ещё лучше делать так: habrahabr.ru/blogs/client_side_optimization/90481/
«There are only two hard problems in Computer Science: cache invalidation and naming things.» Phil Karlton
наткнулся случайно,
про такую возможность писал пять лет назад
habrahabr.ru/post/109050
а вообще было интересно почитать, спасибо
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории