Кэширование с Varnish + ESI

admin

Если на Вашем сайте практически нет динамики, то Вы легко можете складывать все его страницы в кэш и практически не делать запросов к бекенду. Но что делать если на сайте есть персонализированные данные (авторизация, блок пользователя, баннера)?

ESI

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

Всем привет!

Всем пока!!!

Web-сервер, поддерживающий ESI вызовы, просто сделает дополнительный запрос, а результат вставит на место ESI инструкции. Допустим наш скрипт “news.php” содержит такой код:

echo "

    • News title 1

</ul>”;

После обработки первого примера, Web сервер вернет клиенту такую страницу:

Всем привет!

      • News title 1

Всем пока!!!

ESI

Запросы ESI можно кэшировать. Следовательно, у Вас появляется удобное средство работы с динамическим контентом. Достаточно разделить их на разные блоки и закэшировать те, которые не изменяются (либо изменяются редко).

[ad]

Как все работает?

Web сервер, который поддерживает ESI, делает запрос к бекенду (в нашем случае, PHP). Далее получив страницу, обрабатывает все ESI вызовы, делая на каждый из них дополнительный запрос для получения содержимого. Далее складывает (или не складывает) все это в кэш и генерирует страницу. Для последующих вызовов Web сервер будет получать данные из кэша и не делать дополнительных ESI запросов.

Порядок подключения ESI

      1. Сначала нужно определить блоки на странице, вынести их в отдельные скрипты (каждый блок должен иметь свой адрес)
      1. Вставить ESI инструкции на месте вынесенных блоков
      1. Включить кэширование ESI блоков на Web сервере

Персонализированные блоки

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

Стоит учитывать, что количество таких блоков в кэше будет пропорционально количеству пользователей.

общее количество = количество пользователей х количество блоков на страницу

Подробный пример

Пусть у нас есть сайт с новостями. Новости обновляются каждый час. На сайте также есть блок авторизации и ссылки для авторизированных пользователей. Выделяем такие блоки для ESI:

      • Блок авторизации
      • Меню
      • Блок новостей
Стартовая страница

Тестируем ESI

Новости

## Все скрипты для ESI вызовов будут находиться в папке app

Скрипт авторизации

<? if ( $user ) { ?>

Привет, <? } else { ?>

<? } ?>

Скрипт меню

<? session_start(); ?>

    • <? if ( $_SESSION[‘user’] ) { ?>
    • Пункт меню только для пользователей

<? } ?>

Скрипт новостей

$rss = file_get_contents(‘http://feeds.nytimes.com/nyt/rss/HomePage’);

$xml = simplexml_load_string($rss);

echo ”

    • “;
    • foreach ( $xml->channel->item as $item )
    • {
    echo ”
  • “{$item-“>link}” {$item->title}”;
    }
    echo “

“;

Настройка Web сервера

Для приложения будем использовать Nginx, Varnish будет направлять запросы ему (8090 порт):

server {

listen 8090;

# Если включен gzip, обязательно нужно выключить!

gzip off;

location / {

index index.php;

}

location ~* .(php)$ {

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME /home/golotyuk/www/localhost/esi/$fastcgi_script_name;

}

}

Varnish + ESI

Давайте настроим кэш по таким правилам:

    • Главную страницу кэшируем на 24 часа, блоки – на 1 час
    • Кэшировать будем все запросы кроме POST
    • Для кэширования персонального блока будем использовать значение сессионных Cookies (PHPSESSID) – для установки ключа
    • Для отделения персонализированных блоков от обычных блоков для авторизированных пользователей будем использовать соотв. приставки к запросам: UID (персонализированные блоки) и AUTH (обычные блоки, учитывающие только статус пользователя)

Конфигурация:

backend default { .host = “127.0.0.1”; .port = “8090”; }

# Процедура формирования ключа для кэша

sub vcl_hash {

# Стандартные параметры – имя сервера и URL

set req.hash += req.url;

set req.hash += req.http.host;

# Если установлена сессионная кука, сохраняем ее значение в переменную

if( req.http.cookie ~ “PHPSESSID” ) {

set req.http.X-Varnish-Hashed-On =

regsub( req.http.cookie, “^.*?PHPSESSID=([^;]*?);*.*$”, “1” );

}

# Если в строке запроса мы находим “UID”, то необходимо добавить

# значение сессии в параметры кэширования

if( req.url ~ “/app/.*UID” && req.http.X-Varnish-Hashed-On ) {

set req.hash += req.http.X-Varnish-Hashed-On;

}

# Если в строке запроса мы находим “AUTH”, то необходимо добавить

# флаг статуса (logged in) в параметры кэширования

if( req.url ~ “/app/.*AUTH” && req.http.X-Varnish-Hashed-On ) {

set req.hash += “logged in”;

}

hash;

}

sub vcl_recv {

# Если тип запрос не POST, то ищем объект в кэше

if ( req.request != “POST” )

{

lookup;

}

}

sub vcl_fetch {

# Для запроса “/” используем обработку esi и кэшируем на 1 сутки

if (req.url == “/”) {

esi;

set obj.ttl = 24h;

}

# Для запросов “/app” (ESI вызовы) кэшируем результат на 1 час

elseif (req.url ~ “^/app/”) {

set obj.ttl = 1h;

}

deliver;

}

После проверки скорости получим такие результаты:

ab -n 100 -c 5 http://127.0.0.1/
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:     2    5   3.8      3      18
Waiting:        2    5   3.8      3      18
Total:          2    5   3.8      4      19


Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      5
  80%      8
  90%     12
  95%     15
  98%     17
  99%     19
 100%     19 (longest request)

На аналогичном скрипте без ESI, который содержит всю туже логику внутри и каждый раз вызывает PHP:

ab -n 100 -c 5 http://127.0.0.1:8090/index_standard.php

Результаты:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   354  579 666.2    458    5484
Waiting:      354  579 666.2    458    5483
Total:        354  579 666.2    458    5484

Percentage of the requests served within a certain time (ms)
  50%    458
  66%    492
  75%    517
  80%    539
  90%    602
  95%    667
  98%   3572
  99%   5484
 100%   5484 (longest request)

Как видим скорость работы отличается в 100 раз!

Самое важное

ESI позволяет использовать кэширование на динамических сайтах с высокой персонализацией. Обратите внимание на альтернативу – SSI в связке с Nginx.

 

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023