Назад | Перейти на главную страницу

Баланс нагрузки Varnish с переписыванием запросов на сервер

Я пытаюсь сбалансировать нагрузку стороннего веб-приложения с помощью Varnish, и для этого стороннего приложения требуется `` настоящее '' имя сервера (похоже, оно подключается к этому серверу по имени в фоновом режиме (а localhost не работает) :() для передачи в строке запроса. Мне также нужна отработка отказа, а это значит, что я хотел бы использовать директоры, чтобы моя конфигурация была простой и масштабируемой.

Вот простой пример того, что я лайк делать:

sub vcl_pass {
  set bereq.http.X-Varnish-Backend = bereq.backend.name
}

Однако backend.name доступен в beresp только после того, как мы уже сделали запрос. Похоже, что Varnish не решает, какой бэкэнд использовать, пока после vcl_pass завершается, и нет другого хука до того, как запрос будет отправлен на бэкэнд.

Это верно? Если да, то есть ли другое решение (кроме исправления на веб-сервере, которое я не контролирую)? Без циклов, даже если я реализую замену клиентского директора в VCL, он не сможет масштабироваться дальше пары серверов.

Прежде всего, вы должны разработать стратегию, позволяющую различать используемые приложения. Вы можете использовать разные имена хостов (все они указывают на ваш прокси-сервер Varnish) или вы можете использовать разные URL-адреса, чтобы решить, какой запрос должен обрабатываться какой серверной системой. Если у вас есть стратегия, настройте Varnish:

Пример A) Различные имена хостов

Подготовьте все необходимые бэкенды. Это может быть один сервер или несколько серверов с использованием директора:

backend example1 {
  .host = "...";
  .port = "...";
  ...
}

Установите правильный сервер для входящих запросов (в Varnish: req). Я установил дополнительное значение req.http.backend, чтобы использовать его на более позднем этапе. Здесь вы можете заменить или отменить любой HTTP-заголовок клиентского запроса:

sub vcl_recv {
  ...
  if (req.http.host == "example1.mysite.com") {
    set req.backend = example1;
    set req.http.backend = "example1";
    set req.http.host = "application1.internal.mysite.com";
    unset req.http.Cache-Control;
    ...
  }
  ...
}

Внесите некоторые изменения в возвращенный ответ серверной части (в Varnish: beresp). Если у вас есть другое имя хоста для приложения, вы можете изменить перенаправления. Обычно я удаляю некоторые X-заголовки или заменяю кеширующие заголовки back-end здесь:

sub vcl_fetch {
  ...
  if (req.http.backend == "example1") {
    ...
    unset beresp.http.X-Powered-By;
    ...
    if ((beresp.status == 301 || beresp.status == 302) && beresp.http.Location ~ "^http://application1\.internal\.mysite\.com") {
      set beresp.http.Location = regsub(beresp.http.Location, "^http://[^/]+", "http://example1.mysite.com");
    }
  }
  ...
}

Пример Б) разные URL

В Varnish разница заключается в методе vcl_recv. Позаботьтесь о том, чтобы ваше приложение могло работать с путем "/ example1". Возможны и другие решения, но я бы не рекомендовал это:

sub vcl_recv {
  ...
  if (req.http.host == "www.mysite.com") {
    if (req.url ~ "(?i)^/example1/") {
      set req.backend = example1;
      set req.http.backend = "example1";
      set req.http.host = "application1.internal.mysite.com";
      unset req.http.Cache-Control;
      ...
    }
    ...
  }
  ...
}

Вы можете реализовать A или B или объединить A и B. (Более или менее) Все возможно с Varnish.