Настройка Varnish для 1С-Битрикс
PHP-процесс Битрикс генерирует страницу каталога за 200–800 миллисекунд. При 100 одновременных пользователях — сервер в потолке по CPU и памяти. Varnish кеширует HTTP-ответ и отдаёт последующие запросы за 1–5 мс без участия PHP. Но между Varnish и Битрикс есть ряд конфликтов, которые ломают авторизацию, корзину и персональный контент.
Архитектура: Varnish перед Nginx
Стандартная схема: клиент → Varnish (:80/:443) → Nginx (:8080) → PHP-FPM. Nginx при этом переводится на порт 8080. Varnish принимает запросы, кеширует некесируемые отдаёт напрямую бэкенду.
client → varnish:80 → nginx:8080 → php-fpm:9000
↓ (cache hit)
varnish cache (RAM)
Установка на CentOS/RHEL (актуально для Bitrix VM):
yum install varnish
systemctl enable varnish
Ключевые проблемы интеграции с Битрикс
Битрикс использует сессионные куки PHPSESSID и куки авторизации BITRIX_SM_*. Varnish по умолчанию не кеширует запросы с куками — это правильно, но слишком консервативно. Анонимный пользователь с пустой корзиной тоже получает куку сессии и не попадает в кеш.
Второй конфликт — HTTPS. Varnish не терминирует SSL. Нужен Nginx или HAProxy перед Varnish для SSL-терминации. Схема усложняется: клиент → Nginx(:443, SSL) → Varnish(:80) → Nginx(:8080) → PHP-FPM.
Конфигурация VCL для Битрикс
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 5s;
.first_byte_timeout = 120s;
}
sub vcl_recv {
# Принудительно HTTP/1.1 (Varnish не поддерживает HTTP/2 с бэкендом)
set req.http.X-Forwarded-For = client.ip;
# Не кешировать административную панель и авторизацию
if (req.url ~ "^/bitrix/" || req.url ~ "^/area51/") {
return (pass);
}
# Не кешировать POST и авторизованных пользователей
if (req.method == "POST" || req.method == "PUT") {
return (pass);
}
# Авторизованный пользователь — BITRIX_SM_UIDH кука
if (req.http.Cookie ~ "BITRIX_SM_UIDH") {
return (pass);
}
# Корзина не пустая
if (req.http.Cookie ~ "BX_BASKET_ADD") {
return (pass);
}
# Убрать куки, которые не влияют на контент (аналитика, рекламные)
set req.http.Cookie = regsuball(req.http.Cookie,
"(^|;\s*)(_ga|_gid|_gat|_fbp|_ym_uid|_ym_d|_ym_isad)[^;]*", "");
# Если кук не осталось — можно кешировать
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
return (hash);
}
sub vcl_backend_response {
# Не кешировать ответы с Set-Cookie (авторизация)
if (beresp.http.Set-Cookie ~ "BITRIX_SM_") {
set beresp.uncacheable = true;
return (deliver);
}
# Кешировать статику надолго
if (bereq.url ~ "\.(css|js|png|jpg|webp|gif|woff2|ico)$") {
set beresp.ttl = 30d;
set beresp.grace = 1d;
unset beresp.http.Set-Cookie;
return (deliver);
}
# HTML-страницы — 5 минут с grace 1 час
if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 5m;
set beresp.grace = 1h;
}
return (deliver);
}
sub vcl_deliver {
# Отладочный заголовок — убрать на продакшне
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
Инвалидация кеша из Битрикс
При обновлении товара или публикации новости Varnish продолжает отдавать старую страницу до истечения TTL. Нужен механизм принудительной инвалидации.
В bitrix/php_interface/init.php добавить обработчик событий инфоблока:
AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', 'PurgeVarnishCache');
AddEventHandler('iblock', 'OnAfterIBlockElementAdd', 'PurgeVarnishCache');
function PurgeVarnishCache($arFields) {
$url = 'http://127.0.0.1/';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PURGE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Для избирательной инвалидации по тегу:
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-Cache-Tags: catalog']);
curl_exec($ch);
curl_close($ch);
}
В VCL добавить обработку PURGE-запросов от localhost:
sub vcl_recv {
if (req.method == "PURGE") {
if (client.ip != "127.0.0.1") {
return (synth(403, "Not allowed"));
}
return (purge);
}
}
Varnish и Битрикс Composite
Если используется Битрикс Composite (составные страницы с AJAX-подгрузкой динамических блоков) — Varnish кешировать HTML-основу страницы не должен, иначе Composite ломается. Либо выключить кеширование HTML через Varnish и оставить Varnish только для статики, либо настроить Composite на конкретные компоненты без кеширования всей страницы через Varnish.







