среда, 7 апреля 2010 г.

Nginx + Memcached + SSI - кеширование страниц и блоков (partials)

nginx-logo


В одной из предыдущих статей мы рассмотрели, каким образом можно реализовать кеширование страниц с помощью Varnish и ESI. В этой статье рассмотрим альтернативное решение — на основе двух суперзнаменитых продуктов — nginx и memcached.

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



Зачем нужно кешировать страницы?


Довольно детально принципы кеширования страниц и блоков были рассмотрены в предыдущей статье (Varnish + ESI).


В качестве краткого повторения, несколько основных идей и преимуществ кеширования на уровне странц:



  • Кешируя страницы на отдающем сервере, Вы освобождаете ощутимое количество ресурсов на бекендах

  • В случае медленных страниц, значительно уменьшается время ожидания страниц Вашего сайта (ускоряется его работа)

  • Как показывает практика, во многих случаях внедрять систему кеширования странц в готовый проект легче, чем систему кеширования запросов


Nginx и memcached


Nginx позволяет читать данные из Мemcached — для этого Вам необходим модуль HttpMemcachedModule.


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



server {
location / {
set $memcached_key $uri; # Ключ для проверки в memcached
memcached_pass 127.0.0.1:11211; # Параметры подключения
default_type text/html; # Заголовок по умолчанию
error_page 404 @fallback; # 404 — данные в кеше не найдены
}

location @fallback {
proxy_pass backend; # Бекенд
}
}

В данный момент Nginx не умеет сохранять значения в memcached — только читать данные. Значит задача по сохранению страниц в кеш ложится на бекенд. Выглядит это приблизительно так (PHP):



<?
$memcache = new Memcache();
# какой-то код

ob_start();
# визуализация страницы — html
$html = ob_get_clean();

$memcache->set($_SERVER['REQUEST_URI'], $html);
echo $html;
?>

Кеширование блоков и SSI


Если у Вас не самый примитивный сайт (а он у Вас не такой), логика кеширования страниц будет несколько усложнена различными динамическими элементами страницы (блок авторизации, динамическое меню и т.п.). Подобные задачи решаются c помощью SSI — server side includes. Кроме всего прочего использование SSI экономит память, т.к. для каждой страницы Вы не будете хранить ее исходник целиком, а только внутреннюю (изменяемую) часть.


Синтаксис SSI очень простой и выглядит так:



<!--# include virtual="/authentication.php" -->

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


Практический пример


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


Для начала Вам необходимо выделить блоки в Вашем базовом (глобальном) шаблоне и заменить их вызовами SSI. Пример на PHP:



<html>
<body>

<h1>Тестируем nginx + memcached + ssi</h1>

<div class="auth">

<!--# include virtual="/authentication.php" -->
</div>


<!--# include virtual="/somepage.php" -->

</body>
</html>

Как видно, на странице есть два блока — блок авторизации и контентный блок (содержимое странички). В нашем примере блок авторизации будет персональным (допустим, после входа, там будет имя пользователя). Блок содержимого не будет персональным (т.е. он будет общим для всех пользователей).


Теперь необходимо настроить nginx для обработки SSI вызовов и использованию memcached:



# Upstream бекенда
upstream backend {
server 127.0.0.1:8081;
}

server {
listen 80;
server_name test.com;

root /var/www/test;
index index.php;

location / {
# Все POST запросы отправляем на бекенд (не кешируя)
if ($request_method = POST) {
proxy_pass http://backend;
break;
}

# Включаем обработку SSI
ssi on;
default_type text/html;

# Проверяем в мемкеше
set $memcached_key "$uri";
memcached_pass localhost:11211;
proxy_intercept_errors on;
error_page 404 502 = @process;
}

# Сюда запрос приходит, если его небыло в кеше
location @process
{
proxy_pass http://backend;
ssi on;
}
}

# Обычный бекенд
server {
listen 8081;

location ~* \.(php)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/test$fastcgi_script_name;
}
}

Следующим шагом в приложении необходимо будет реализовать сохранение исходников страниц в memcached.


Кеширование персонализированных блоков


Ясно, что для кеширования персонализированных блоков необходимо добавить идентификатор пользователя (не вздумайте использовать внутренний ID пользователя) в ключ memcached. SSI вызов необходимо пометить, чтобы отличать персональные блоки от общих. Т.е. персональный вызов SSI будет иметь такой вид:




<!--# include virtual="/uid/authentication.php" -->
</div>

Для генерации memcached ключей с идентификатором пользователя можно использовать куки (устанавливать его будет приложение при авторизации пользователя):



set $memcached_key "$uri:$cookie_uid";

Соответственно, необходимо в nginx добавить обработчик для “/uid” запросов:



location /uid {
ssi on;
default_type text/html;

set $memcached_key "$uri:$cookie_uid";
memcached_pass localhost:11211;
proxy_intercept_errors on;
error_page 404 502 = @process;
}

Естественно, в самом приложении все “/uid” запросы должны кешироваться с идентификатором пользователя:



$m->set($_SERVER['REQUEST_URI'] . ':' . $_COOKIE['uid'], $html);

Следует обратить внимание


Недавно появился продукт, который должен стать типичным решением при кешировании страниц — Twicecache. Пока он на очень ранней стадии и доступны только его исходники. Будем внимательно следить.



Google Bookmarks Digg I.ua Ru-marks Ruspace Zakladok.net Reddit delicious Technorati Yahoo My Web News2.ru БобрДобр.ru Memori.ru rucity.com



Related posts:

  1. Кеширование страниц — ускоряем сайт в 100 раз (Varnish + ESI)
  2. Настройка nginx
  3. Ресайзинг картинок в nginx

Комментариев нет:

Отправить комментарий