Кеширование высоконагрузочных порталов средствами NGINX

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

В этой статье мы расскажем о своем опыте применения веб-сервера NGINX для полного кеширования страниц высоконагруженного портала.

Проектируемый нами портал должен был выдерживать нагрузку в 1 млн. одновременных посетителей, поэтому сразу встал вопрос как обеспечить максимальную производительность, сведя до минимума обращения к тяжелым скриптам на бекенд-серверах. Решение в виде очень активного кеширования и прегенерации блоков напрашивалось само собой, т.к. портал предполагал высокую статичность большинства страниц. Такое утверждение применимо к очень многим сайтам, от новостных ресурсов до видео порталов. Каждой единице контента (новость или видео клип) соответствует своя страница на которой лишь несколько элементов могут меняться. Кроме того, относительное количество зарегистрированных пользователей как правило очень мало. В нашем случае, страница отдаваемая авторизованному и не авторизованному пользователю заметно отличается наличием динамических элементов (рейтинги, голосования, личный кабинет, статистика) — поэтому было создано два независимых кеш-хранилища для целых страниц. Выдача страницы для анонимного посетителя весьма тривиальна (она одинаковая для всех). А вот генерация страницы для авторизованного посетителя сопровождается вызовом Ajax метода, на основании ответа которого JavaScript страницы обновляет основные элементы. Это позволяет перенести затраты ресурсов по генерации страницы на сторону клиента тем самым еще сильнее освободив серверное оборудование.

Пример конфигурационного файла:

1
2
3
4
5
6
http {
…......
fastcgi_cache_path /data/static/cache levels=1:2 keys_zone=cache:4096m;
fastcgi_cache_path /data/static/cacheauth levels=1:2 keys_zone=cacheauth:2048m;
…......
}

В секции http конфигурационного файла NGINX определяем две директории для размещения кеш-файлов, задаем имена для зон, по которым будут идти обращения к кеш-файлам и задаем объем дискового пространства, отведенный под кеш.
Ключом и именем файла в кэше будет являться результат работы функции md5 от проксированного URL.

На период отладки кеша рекомендуется использовать минимальные уровни кеширования, для отслеживания попадений запросов в кеш.

1
location / {

if ($http_cookie ~* «AUTH») {

#Организуемый внутренний редирект на соответсвующую секцию

#конфигурационного файла

return 412;
error_page 412 = @authorized;
}

if ($cookie_AUTH = »)
{
return 414;
error_page 414 = @nonauthorized;
}
}

Проверка авторизации пользователя производится прямо на frontend-серверах по средством анализа передаваемых cookies в http-запросе. В зависимости от результата проверка кук страница отдается пользователю из разных веток кеша.

Пример конфигуроционного файла для пользователей прошедших авторизацию:

1
2
3
#Здесь мы определяем URL кеширование которых не должно просиходить, данные должны отдаваться напрямую с backend-серверов
location @authorized
{

#Все поисковые запросы отправляем сразу на бекенды, в обход кеширования
if ($request_uri ~* /search/*)
{
…….
}

root           /data/www/project/public;
fastcgi_pass   10.20.40.6:9000;
fastcgi_index  index.php;
fastcgi_param  SCRIPT_FILENAME  /data/www/project/public$fastcgi_script_name;
include        fastcgi_params;

#Задаем используемую зону кеширования
fastcgi_cache cacheauth;

#Время кеширования 304-ответа от сервера
fastcgi_cache_valid 304 1m;

#Время жизни кеш-файлов
fastcgi_cache_valid any 10m;

#Разрешаем передавать cookie
fastcgi_pass_header Cookie;

#Разрешаем выставлять Cookie клиенту
fastcgi_pass_header «Set-Cookie»;

#Игнорируем заголовки управления кешом на стороне клиента
fastcgi_ignore_headers «Cache-Control» «Expirere”
fastcgi_hide_header «Pragma»;
add_header Pragma «no-cache»;
expires -1;
fastcgi_intercept_errors off;

#Задаем ключ кеширования
fastcgi_cache_key «$server_addr:$server_port$request_uri»;

#Добавляем заголовки
add_header Cache-Control «no-store, no-cache”;

add_header “must-revalidate,post-check=0,pre-check=0»;

}

Данная конфигурация обеспечивает отличную производительность проекту, отдавая около 90% страниц из кеша, минимизируя нагрузку на бекенд-серверы, выполняющие «тяжелые» операции.

В следующей нашей статье мы расскажем о том, как использовать кеширование и технологию AIO при отдаче видеофайлов в режиме Progressive Download средствами NGINX для построения высокопроизводительного кластера по раздаче виде контента.