#apache #nginx #varnish #varnish-vcl
#apache #nginx #varnish #varnish-vcl
Вопрос:
У меня есть установка с Apache2, nginx и Varnish над ними. Varnish получает запрос, определяет, для какого бэкэнда он предназначен (статический отправляется в nginx, динамический — в Apache), извлекает ответ из бэкэнда и при необходимости кэширует его.
Среди прочего Apache генерирует эскизы. Он создает эскизы, используя определенную логику, и это довольно дорого для процессора. Таким образом, Apache сохраняет thumb на диск, чтобы в следующий раз, когда будет получен запрос на этот эскиз, Varnish мог перенаправить его непосредственно в nginx.
И вот в чем проблема: Varnish не имеет возможности проверить, существует ли файл где-то в файловой системе, и поэтому он не знает, можно ли использовать серверную часть nginx или Apache должен сначала сгенерировать эскиз.
Решение, которое я принял в настоящее время, довольно простое, но уродливое:
- Varnish получает запрос на миниатюру;
- Varnish отправляет запрос в nginx;
- Если nginx не может найти файл миниатюр, он выдает ошибку 404, и Varnish перенаправляет запрос на Apache.
Хотя этот алгоритм кажется простым, на самом деле это не так. В файле конфигурации VCL требуется следующая реализация:
vcl_recv
Всегда предполагайте, что эскиз существует, и все запросы должны быть перенаправлены на nginx, если они не запрашиваются с какого-либо специального хоста;- В
vcl_fetch
catch object HTTP status и если он равен 404, а ресурс является миниатюрой, чем перезаписать хост на специальный и перезапустить процесс:
VCL:
if( obj.status == 404 ) {
if(req.url ~ "^thumb/") {
set req.http.host = "thumb_generator.site.com";
set req.url = regsub(req.url, "/thumb/(filename)", "thumb_gen.php?filename=1");
restart;
}
}
Может быть, есть несколько лучших способов решить эту проблему? Я знаю, что Varnish поддерживает C в VCL, может быть, лучше проверить наличие файла с помощью C-кода?
Комментарии:
1. Пожалуйста, используйте тег varnish-vcl вместо vcl, поскольку vcl уже является популярным тегом в сообществе Delphi. Сегодня мод переназначил все теги varnish vcl.
Ответ №1:
Хорошо, если кто-то заинтересован в решении, я нашел новое решение со встроенным C в конфигурации VCL. Прежде всего, мы должны добавить функцию для проверки существования файла (добавьте где-нибудь в верхней части вашего файла вне какой-либо функции):
C{
#include <stdio.h>
#include <stdlib.h>
int exists (char *fname)
{
FILE *file;
if (file = fopen(fname, "r"))
{
fclose(file);
return 1;
}
return 0;
}
}C
Я знаю, что есть лучшие способы проверить, существует ли файл, но основные заголовки недоступны внутри VCL :/
Затем в vcl_recv
подпрограмме добавьте следующий код:
C{
if( exists("/local/file/path") == 1 ) {
VRT_l_req_backend(sp, VCL_conf.director[1]);
} else {
VRT_l_req_backend(sp, VCL_conf.director[2]);
}
}C
Работает как шарм.
Комментарии:
1. Прелести не работают. Но хорошее решение! Если вы пытаетесь уменьшить задержку, вы можете вместо этого использовать fstat() для файла, который, я полагаю, выполняет меньше операций ввода-вывода на диске. На самом деле он не открывает файл, он просто подтверждает, что файл находится там из записи каталога: linux.die.net/man/2/fstat
Ответ №2:
Вы используете Varnish для чего-то, для чего он не был создан. Действительно, у него нет возможности проверить, существует ли файл, потому что он изначально не был создан для обслуживания файлов. Varnish просто временно кэширует ответы сервера в файле или в памяти.
Вам действительно нужен varnish в этой настройке? Разве не было бы гораздо разумнее, если бы nginx проверил, существует ли файл, или переслал его вашему процессору?
Ответ №3:
Почему бы не использовать директиву try_files от Nginx для автоматической передачи запроса Apache на 404? Это казалось бы более логичным, по крайней мере, для меня.
Ответ №4:
Вас, вероятно, заинтересует libvmod-utils. У вас будет доступ к тому, что предложил WASSD42, но непосредственно с помощью VMOD (более чистого, и должны применяться последние улучшения и советы) вместо встроенного-C.
Встроенный C хорош тем, что вы можете делать все, что вам нужно, но иногда наличие VMOD более чистое и позволит не нарушать ваш язык VCL.
Ниже приведен пример VCL, реализующий ваши потребности :
import utils;
sub vcl_recv {
if(req.url ~ "^/thumb/") {
if (utils.exists("/srv/www/static/" req.url)) {
set req.backend = nginx;
else {
set bereq.url = regsub(req.url, "/thumb/(filename)", "thumb_gen.php?filename=1");
set req.backend = apache;
}
}
}