Создание контента с помощью Edge Side Includes
Varnish может создавать веб-страницы, собирая различные страницы, называемые fragments, в одну. Эти fragments могут иметь отдельные политики кэширования. Если у вас есть веб-сайт со списком пяти самых популярных статей, этот список, вероятно, можно кэшировать как fragment и включать во все остальные страницы.
Правильное использование этой стратегии может значительно повысить коэффициент попадания и снизить нагрузку на серверы.
В Varnish реализована только небольшая подборка спецификаций ESI, так как большая часть других возможностей ESI проще и лучше реализуется с помощью VCL:
esi:include esi:remove <!--esi ...-->
Подстановка контента на основе переменных и куки не реализована.
Varnish не будет обрабатывать инструкции ESI в HTML комментариях.
Пример: esi:include
Давайте рассмотрим пример использования. Этот простой скрипт CGI выводит текущую дату:
#!/bin/sh echo 'Content-type: text/html' echo '' date "+%Y-%m-%d %H:%M"
Теперь давайте рассмотрим HTML-файл, содержащий инструкцию ESI include:
<HTML> <BODY> The time is: <esi:include src="/cgi-bin/date.cgi"/> at this very moment. </BODY> </HTML>
Для работы ESI необходимо активировать обработку ESI в VCL, например так:
sub vcl_backend_response {
if (bereq.url == "/test.html") {
set beresp.do_esi = true; // Do ESI processing
set beresp.ttl = 24 h; // Sets the TTL on the HTML above
} elseif (bereq.url == "/cgi-bin/date.cgi") {
set beresp.ttl = 1m; // Sets a one minute TTL on
// the included object
}
}
Обратите внимание, что set beresp.do_esi = true; не требуется и следует избегать для включённых фрагментов, если только они также не содержат <ESI::include …/> инструкции.
Пример: esi:remove и <!–esi … –>
Конструкции <esi:remove> и <!–esi … –> могут использоваться для отображения соответствующего контента с учётом наличия ESI, например, вы можете включать контент, когда ESI доступен, или ссылаться на него, когда он недоступен. Процессоры ESI удалят начальную (“<!–esi”) и конечную (“–>”) части при обработке страницы, но при этом обработают содержимое. Если страница не обрабатывается, она останется неизменной, став HTML/XML комментарием. Процессоры ESI удалят <esi:remove> теги и всё содержимое внутри них, позволяя отобразить контент только при отсутствии обработки страницы через ESI. Например:
<esi:remove> <a href="http://www.example.com/LICENSE">The license</a> </esi:remove> <!--esi <p>The full text of the license:</p> <esi:include src="http://example.com/LICENSE" /> -->
Что происходит при ошибке?
По умолчанию фрагменты должны иметь код состояния resp.status 200 или 206, иначе родительский запрос будет прерван.
Аналогично, если фрагмент представляет собой потоковую загрузку, и эта загрузка завершится ошибкой, родительский запрос прерывается.
Если вы включаете синтетические фрагменты, то есть фрагменты, созданные в vcl_backend_error{} или vcl_synth{}, вы должны установить (be)resp.status в 200 перед return(deliver);
Мы говорим «прервать», а не «ошибиться», потому что к моменту, когда Varnish начинает вставлять фрагменты, заголовок HTTP-ответа уже давно отправлен, и изменить родительский запрос на код состояния 5xx уже нельзя, поэтому единственный способ указать, что что-то не так, — это закрыть соединение.
Однако, можно разрешить отдельным <ESI:include… продолжить работу в случае ошибок, установив:
param.set feature +esi_include_onerror
и помечая эти конкретные include:
<ESI:include src="…" onerror="continue"/>
Может ли фрагмент ESI также использовать ESI-include?
Да, но глубина ограничена параметром max_esi_depth для предотвращения бесконечной рекурсии.
Использование ESI с JSON и другими не XML-подобными данными
Varnish просмотрит первый байт объекта и, если он не «<», Varnish предположит, что вы не хотели обрабатывать его через ESI. Вы можете отключить эту проверку, выполнив:
param.set feature +esi_disable_xml_check
Игнорирование BOM в объектах ESI
Если ваш бэкенд выводит Unicode Byte-Order-Mark в качестве первых байтов ответа, проверка «<» завершится ошибкой, если вы не установите:
param.set feature +esi_remove_bom
ESI при некорректном XML
Парсер ESI ожидает, что XML будет в разумной степени корректным, но это может не сработать, если вы включаете не XML-файлы с помощью ESI. Вы можете заставить парсер ESI игнорировать все, кроме тегов ESI, установив:
param.set feature +esi_ignore_other_elements
ESI include с протоколом HTTPS
Если теги ESI:include указывают протокол HTTPS, он будет проигнорирован по умолчанию, так как у Varnish нет возможности загрузить его с шифрованием. Если вы хотите, чтобы Varnish загружал их как обычные файлы, установите:
param.set feature +esi_ignore_https
ESI для частичных ответов (206)
Varnish поддерживает запросы диапазонов, но в общем случае частичные ответы не имеют смысла в контексте ESI.
Если вы точно знаете, что делаете, измените 206 на 200:
sub vcl_backend_response {
if (beresp.status == 206 && beresp.http.secret == "swordfish") {
set beresp.do_esi = True;
set beresp.status = 200;
}
}
ESI и return(vcl(…))
Если исходный клиентский запрос переключился на другой VCL, используя return(vcl(...)) в vcl_recv, все запросы esi:include по-прежнему будут начинаться в том же VCL, что и исходный, а не в том, на который он переключился.
ESI и сжатие gzip
Реализация ESI в Varnish автоматически обрабатывает сжатие gzip, независимо от того, как оно смешано: родительский запрос может быть сжат или нет, а фрагменты могут быть сжаты или нет — всё работает.
Varnish выполняет сжатие всех частей ответов ESI по отдельности и склеивает их во время доставки, что негативно влияет на коэффициент сжатия.
Когда вы set beresp.do_esi = True; сжатый gzip-ответ, он будет разархивирован и заново сжат по частям во время загрузки.
Частичное сжатие уменьшает возможности удаления избыточности, потому что обратные ссылки в потоке данных gzip не могут указывать на фрагменты за пределами своей части.
Другой случай, когда коэффициент сжатия страдает, — это если несжатый фрагмент вставляется в сжатый ответ.
Copyright © 2006 Verdens Gang AS
Copyright © 2006–2020 Varnish Software AS
Licensed under the BSD-2-Clause License.
https://varnish-cache.org/docs/7.4/users-guide/esi.html