У меня установка с Apache2, nginx и Varnish над ними. Varnish получает запрос, определяет, для какого бэкенда он нужен (статический отправляется nginx, динамический — Apache), получает ответ от бэкенда и при необходимости кэширует его.
Помимо прочего, Apache генерирует эскизы. Он создает эскизы, используя некоторую специфическую логику, и это довольно дорого для процессора. Таким образом, Apache сохраняет thumb на диск, чтобы в следующий раз запрос на этот thumbnail был получен, Varnish мог бы перенаправить его прямо на nginx.
И вот проблема: Varnish не может проверить, существует ли файл где-то в файловой системе, и поэтому он не знает, можно ли использовать бэкенд nginx или Apache должен сначала создать миниатюру.
Обходной путь, который я сейчас принял, довольно прост, но уродлив:
- Varnish получает запрос на миниатюру;
- Varnish отправляет запрос в nginx;
- Если nginx не может найти файл эскиза, он отвечает ошибкой 404, а Varnish перенаправляет запрос на Apache.
Хотя этот алгоритм кажется простым, на самом деле это не так. В файле конфигурации VCL необходима следующая реализация:
- В
vcl_recv
всегда предполагайте, что миниатюра существует и все запросы должны быть перенаправлены на nginx, если они не запрашиваются с какого-то специального хоста; - В
vcl_fetch
перехватите HTTP-статус объекта, и если он 404, а ресурс миниатюрный, то перепишите хост на специальный и перезапустите процесс:
ВКЛ:
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-кода?