Як використовувати Varnish для прискорення мого сайту
Дата оновлення перекладу 2023-09-19
Як використовувати Varnish для прискорення мого сайту
Так як кеш Symfony використовує стандартні HTTP кеш заголовки, може бути з легкістю замінено будь-яким іншим зворотнім проксі. Varnish - це потужний відкритий HTTP-акселератор, здатний швидко обслуговувати кешування змісту, включно з підтримкою Включень крайнніх сторін (ESI).
Змушуємо Symfony довіряти зворотньому проксі
Varnish автоматично пересилає IP як X-Forwarded-For
і залишає заголовок
X-Forwarded-Proto
у запиті. Якщо ви не сконфігуруєте Varnish як довірений
проксі, то Symfony бачитиме всі запити, як ті, що виходять від незахищених HTTP
з'єднань хостингу Varnish, а не від реального клієнту.
Не забудьте викликати метод Request::setTrustedProxies() у вашому фронт-контролері, щоб Varnish виглядав як довірений проксі та були використані заголовки X-Forwarded-* .
Маршрутизація та заголовки X-FORWARDED
Щоб переконатися в тому, що маршрутизатор Symfony правильно генерує URL з
Varnish, має бути присутнім заголовок X-Forwarded-Port
, щоб Symfony
використовувала правильний номер порту.
Цей номер порту відповідає тому, що використовує ваша установка для вилучення
зовнішніх зв'язків (80
- значення за замовчуванням для HTTP-з'єднань). Якщо
застосунок також приймає HTTP-з'єднання, то може бути ще один проксі (так як Varnish
сам не робить HTTPS) в порту HTTPS за замовчуванням 443, який обробляє завершення
SSL та пересилає запити як HTTP-запити у Varnish із заголовком X-Forwarded-Proto
.
В цьому випадку, вам необхідно додати наступний відрізок конфігурації:
1 2 3 4 5 6 7
sub vcl_recv {
if (req.http.X-Forwarded-Proto == "https" ) {
set req.http.X-Forwarded-Port = "443";
} else {
set req.http.X-Forwarded-Port = "80";
}
}
Куки та кешування
За замовчуванням, більшість проксі, що кешують, не кешують нічого, якщо запит відправлено з куки або базовим заголовком аутентифікації . Це тому, що зміст сторінки має залежати від значення куки або заголовку аутентифікації.
Якщо ви точно знаєте, що вихідний буфер ніколи не використовує сесії або базову аутентифікацію, зробіть так, щоб Varnish видалив відповідний заголовок із запитів, щоб запобігти обхід кешування клієнтами. На практиці, вам знадобляться сесії як мінімум для деяких частин сайту, наприклад, при використанні форм з CSRF-захистом. В цій ситуації, переконайтеся, що ви починаєте сесію лише тоді, коли це дійсно необхідно та очищуєте сесію, коли вона вже не потрібна. Як варіант, ви можете розглянути кешування сторінок, які містять форми із захистом від CSRF .
Кукі, створені в JavaScript та використані лише у вхідному буфері (фронт-енді), наприклад,
при використанні Google Analytics, тим не менше відправляються серверсу. Ці куки неважливі
для вихідного буферу та не мають впливати на рішення кешування. Сконфігуруйте ваш кеш
Varnish, щоб він очищував заголовок куки. Вам варто залишити куки сесії, якщо вони є, та
позбавитися всіх інших, щоб сторінки кешувалися, якщо активної сесії немає. Якщо ви не змінювали
конфігурацію PHP за замовчуванням, то ваш куки сесії має ім'я PHPSESSID
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
sub vcl_recv {
// Видалити всі куки, окрім ID сесії.
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, ";(PHPSESSID)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie == "") {
// Якщо куки більше немає, видаліть заголовок для кешування сторінки.
unset req.http.Cookie;
}
}
}
Tip
Якщо зміст не відрізняється для кожного користувача, але залежить від ролей користувача, то рішенням буде розділяти кешування за групами. Ця схема реалізується та пояснюється FOSHttpCacheBundle під назвою Контекст користувача.
Гарантія послідовної поведінки кешування
Varnish використовує заголовки кешу, відправлені вашим додатком, щоб визначити,
як кешувати зміст. Однак, версії Varnish до 4 не поважали Cache-Control: no-cache
,
no-store
та private
. Щоб гарантувати послідовну поведінку, використайте
наступну конфігурацію, якщо ви все ще використовуєте Varnish 3:
1 2 3 4 5 6 7 8 9 10
sub vcl_fetch {
/* За замовчуванням, Varnish3 ігнорує Cache-Control: no-cache та private
// https://www.varnish-cache.org/docs/3.0/tutorial/increasing_your_hitrate.html#cache-control
if (beresp.http.Cache-Control ~ "private" ||
beresp.http.Cache-Control ~ "no-cache" ||
beresp.http.Cache-Control ~ "no-store"
) {
return (hit_for_pass);
}
}
Tip
Ви можете побачити поведінку Varnish за замовчуванням у формі VCL-файлу: default.vcl для Varnish 3, builtin.vcl для Varnish 4.
Активація включень крайніх сторін (ESI)
Як пояснюється у статті про ESI, Symfony визначає, чи
спілкується вона зі зворотнім проксі, який розуміє ESI. Коли ви використовуєте
зворотній проксі Symfony, вам не потрібно нічого робити. Але щоб змучити Varnish
вирішувати ESI-теги замість Symfony, вам потрібна деяка конфігурація у Varnish.
Symfony використовує заголовок Surrogate-Capability
з Edge Architecture,
описаний Akamai.
Note
Varnish підтримує лише атрибут src
для ESI-тегів (атрибути onerror
та alt
ігноруються).
Для початку, сконфігуруйте Varnish так, щоб він афішував свою підтримку ESI
шляхом додавання заголовку Surrogate-Capability
у запити, які пересилаються
додатку вихідного буферу:
1 2 3 4
sub vcl_recv {
// Додати заголовок Surrogate-Capability, щоб афішувати підтримку ESI.
set req.http.Surrogate-Capability = "abc=ESI/1.0";
}
Note
Частина заголовку abc
не важлива, окрім випадків, коли у вас багато
"сурогатів", які мають афішувати свої можливості. Дивіться
Заголовок Surrogate-Capability, щоб дізнатися деталі.
Далі, оптимізуйте Varnish так, щоб він аналізував зміст відповіді лише
тоді, коли в ньому є хоча б один ESI-тег, перевіряючи заголовок Surrogate-Control
,
який Symfony додає автоматично:
1 2 3 4 5 6 7
sub vcl_backend_response {
// Перевірити підтвердження ESI та видалити заголовок Surrogate-Control
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
}
Tip
Якщо ви послухалися поради про гарантування послідовної поведінки кешування, то ці VCL-функції вже існують. Просто додайте код до кінця функції, і вони не заважатимуть одне одному.
Інвалідація кешу
Якщо ви хочете кешувати зміст, який часто змінюється, і все одно відправляти користувачам найсвіжішу версію, то вам потрібно інвалідувати цей зміст. В той час як інвалідація кешу дозволяє вам вилучати зміст з вашого проксі до того, як сплине строк дії, вона додає складнощі до вашої установки кешування.
Tip
FOSHttpCacheBundle відкритого доступу позбавляє від головного болю з інвалідацією, допомагаючи вам організувати вашу установку кешування та інвалідації.
Документація FOSHttpCacheBundle пояснює, як сконфігурувати Varnish та інші зворотні проксі для інвалідації кешування.