Хороший способ выбора между бэкэндами от Varnish в зависимости от наличия запрашиваемого файла - PullRequest
2 голосов
/ 02 ноября 2011

У меня есть установка с Apache2, nginx и Varnish над ними.Varnish получает запрос, определяет, для чего он предназначен (статический идет в nginx, динамический идет в Apache), получает ответ от внутреннего и кэширует его при необходимости.

Помимо прочего, Apache генерирует миниатюры.Он создает эскизы с использованием определенной логики и довольно дорог для процессора.Таким образом, Apache сохраняет большой палец на диск для того, чтобы в следующий раз запрос на эту миниатюру был получен, Varnish мог перенаправить его напрямую на nginx.

И вот проблема: Varnish не имеет возможности проверитьесли файл существует где-то в файловой системе, и поэтому он не знает, можно ли использовать бэкэнд nginx или Apache должен сначала создать миниатюру.

Обходной путь, который я сейчас выбрал, довольно прост, но уродлив:

  1. Varnish получает запрос на миниатюру;
  2. Varnish отправляет запрос на nginx;
  3. Если nginx не может найти файл миниатюр, он отвечает с ошибкой 404 и Varnish перенаправляет запрос наApache.

Хотя этот алгоритм кажется простым, на самом деле это не так.В конфигурационном файле VCL необходима следующая реализация:

  1. В vcl_recv всегда предполагается, что миниатюра существует, и весь запрос должен быть перенаправлен на nginx , если он не запрашивается с какого-либо специального хоста ;
  2. В vcl_fetch перехватить состояние HTTP объекта, и если оно равно 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-кода?

Ответы [ 4 ]

4 голосов
/ 02 ноября 2011

ОК, если кто-то заинтересован в решении, я нашел новый со встроенным 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

Работает как шарм.

2 голосов
/ 02 ноября 2011

Вы используете Varnish для чего-то, для чего он не был создан. У него действительно нет возможности проверить, существует ли файл, потому что он не был создан для обслуживания файлов. Лак только временно кэширует внутренние ответы в файле или памяти.

Вам действительно нужен лак в этой настройке? Разве не имеет смысла проверять nginx, существует ли файл, или пересылать его на ваш процессор?

1 голос
/ 13 февраля 2014

Возможно, вас заинтересует libvmod-utils .У вас будет доступ к тому, что предлагал WASD42, но напрямую с VMOD (более чистым, и должны применяться последние улучшения и советы) вместо inline-C.

Inline-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;
        }
    }
}
1 голос
/ 04 февраля 2012

Почему бы не использовать директиву Nginx try_files , чтобы молча прокси-запрос к Apache на 404?Это было бы более логично, по крайней мере, мне.

...