При кешировании в varnish возникает вопрос, какие данные использовать для генерации хеш-функции кеша. Типично используют req.url и reg.http.Cookie. Но включение куки приводит к тому, что страницы не попадают в кеш Varnish.
Типовая генерация хеша в varnish 4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
sub vcl_hash { # адрес объекта hash_data(req.url); # для мультисайтинга с похожей структурой сайтов # стоит добавить значение host if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } # добавляем куки if (req.http.Cookie) { hash_data(req.http.Cookie); } return (lookup); } |
Страница (HTML код) может зависеть от значений, хранящихся в cookie, потому приходиться добавлять эту переменную. Но современные сайты в большинстве случаев генерируют куки, связанные с аналитикой, сбором информации о пользователе третьей стороной и т.п., не имеющие никакой ценности для самого сайта.
Многие из них начинаются с символа подчеркивания, потому не сложно почистить их в секции vcl_recv:
1 |
set req.http.Cookie = regsuball(req.http.Cookie, "(?<=\s|^)_[^=]*=[^;]+(; )?", ""); |
Но, к сожалению, не все куки, делающие на практике кеширование страниц в varnish бесполезным, следуют этому правилу. Попытки очистить известные куки правилами вроде:
1 |
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", ""); |
рано или поздно приводят к пониманию, что сложно предсказать какие ещё куки захочет создавать facebook или google.
Вместо черного списка, более надежно создать белый список переменных cookie, которые влияют на внешний вид страницы, и для комбинации значений которых можно/нужно сохранить отдельный экземпляр в кеше.
Для этого следует обладать полной «картой» переменных cookie вашего веб-приложения (сайта), понимать как они могут влиять на HTML код.
Вариант 1 — Маркировка и замена
Довольно изящный вариант, вполне рабочий, найденный мной в сети. Скорее всего написан из-за не очень глубоких знаний регулярных выражений.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
sub vcl_recv { if (req.http.Cookie) { // добавим ; в начала куки set req.http.Cookie = ";" + req.http.Cookie; // идея в том, что куки разделены двумя символами - "; " // автор удаляет пробелы set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); // а куки из белого списка маркирует вновь разделителем с пробелом set req.http.Cookie = regsuball(req.http.Cookie, ";(COOKIE1|COOKIE2)=", "; \1="); // последней заменой мы удаляем все куки без пробела перед именем set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); } } |
Арсенал функций varnish 4 очень скромный. Потому идея была интересная, и я знакомлю вас с ней.
Вариант 2 — сложная замена
Все это можно сделать единственным вызовом функции regsuball, но приходится прибегать к редко используемому синтаксису регулярных выражений.
1 |
set req.http.Cookie = regsuball(req.http.Cookie, "(?<=\s|^)(?!COOKIE1|COOKIE2)[^=]+=[^;]+(; )?", ""); |
«Lookbehind» конструкция (?<=\s|^) позволяет нам проверить, что перед искомым выражением идет пробел или начало строки. А условные выражения (?! … ) позволяют отфильтровать переменные по «белому» списку.