Сайт Романа ПарпалакаБлог20200828

Кеширование в nginx

28 августа 2020 года, 22:12

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

Я уже писал о том, как работает мой сервис генерации картинок с формулами на латехе. При первом обращении к какой-либо формуле php-скрипт запускает латех и сохраняет картинку в папку с кешем. При последующих обращениях к этой формуле веб-сервер сам отдает содержимое файла без потребления значительных ресурсов сервера. Новые формулы появляются существенно реже, чем запрашиваются старые. Система работает практически идеально. Единственная проблема — работа с пустым кешем.

Иногда папку с кешем приходится удалять, если она слишком сильно разрослась. Или если я вношу правки в систему, и кеш устаревает. Посетители популярных страниц генерируют множество запросов к одинаковым формулам. В кеше их нет. Nginx направляет запросы к PHP. PHP на каждую формулу вызывает консольный скрипт латеха. Раньше у меня не было защиты от того, чтобы сервер в нагруженном состоянии хотя бы не делал одно и то же много раз. Это классическое условие гонки.

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

В блоке конфигурации http указываем папку и другие параметры зоны кеша:

fastcgi_cache_path /var/data/i.upmath.me levels=1:2 keys_zone=i_upmath:10m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Обратите внимание на ключ кеширования. Я использовал обычный адрес ресурса, потому что картинки публичны и одинаковы для всех. Если у вас закрытые ресурсы, можете попробовать добавить куки в ключ. Хотя я бы не стал так делать: велик риск ошибки и утечки чужих приватных данных через кеш.

Далее в нужном location подключаем зону:

fastcgi_cache i_upmath;
fastcgi_cache_valid 200 10m;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_lock on;
fastcgi_cache_lock_age 9s;
fastcgi_cache_lock_timeout 9s;

Помимо кеширования здесь включена блокировка для предотвращения race condition. Длительность блокировки и ожидания я выбрал 9 секунд, потому что таймаут запуска латеха в моей системе 8 секунд. Вы можете подобрать другое значение.

На моем сервере ограниченное количество процессов php-fpm могут генерировать картинки. Это сделано, чтобы не мешать другим сайтам. Чтобы после очистки кеша запросы к картинкам дожидались их генерации, я увеличил таймауты nginx для ожидания бэкенда:

fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_connect_timeout 90;
fastcgi_send_timeout 90;

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

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

Поделиться

Кеширование и условие гонки Ctrl Одновременная вставка уникальных значений в словарные таблицы — В кресле препода №3

Читайте также

Латех и веб-технологии
В прошлый раз я рассказал о своем сервисе, который генерирует для веба картинки с математическими формулами на латехе. Теперь я расскажу, как заставить программное обеспечение (TeX Live, nginx, php-fpm, SVGO) и технологии (HTML, CSS, JS, SVG) работать вместе, чтобы получился такой результат.
2014
Маркировка чипов
Внушительная коллекция маркировок когда-либо изготовленных чипов. Когда вам, например, покажут чип и скажут, что это 486 процессор, с помощью этого ресурса вы определите, что это вовсе не процессор, а кеш, и не дадите провести себя.
2005
Очередь на основе PHP-FPM
Применил на практике прием, когда асинхронная очередь обработки сообщений реализовывается через PHP-FPM по протоколу fastcgi. На удивление, всё заработало сразу, никакой наладки не потребовалось.
2020
Отладка запросов к FastCGI из консоли
Обычно протокол FastCGI применяется для общения между веб-сервером и бэкендом. Например, связка nginx и PHP-FPM работает по этому протоколу.
2023

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


Формулы на латехе: $$f(x) = x^2-\sqrt{x}$$ превратится в $$f(x) = x^2-\sqrt{x}$$.
Выделение текста: [i]курсивом[/i] или [b]жирным[/b].
Цитату оформляйте так: [q = имя автора]цитата[/q] или [q]еще цитата[/q].
Других команд или HTML-тегов здесь нет.

Записи