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

Проблема балансировки нагрузки nginx с 301 от бэкэнда

У меня возникла странная проблема, из-за которой я не уверен, проблема ли это в конфигурации или ошибка в nginx. Моя установка - это обратный прокси-сервер nginx с внутренними серверами Apache2. Балансировщик нагрузки довольно прост, похож на пример из вики, например упрощенный:

http {
  upstream myproject {
    server 127.0.0.1:8000;
  }

  server {
    listen 80;
    location / {
      proxy_pass http://myproject;
    }
  }
}

Теперь проблема возникает, например, когда я пытаюсь запросить каталог в Apache без косой черты в конце URL-адреса. Например, клиент запрашивает:

http://apache.myserver.com/somedirectory

Apache ответит HTTP 302, чтобы перенаправить клиента на

http://apache.myserver.com/somedirectory/

Обратите внимание, что URL-адрес в конце имеет косую черту, чтобы указать, что это каталог. Также обратите внимание, что Apache «умный», используя имя хоста входящего запроса в заголовке перенаправления. Пока все в порядке. Однако при использовании nginx с балансировкой нагрузки этот 301 отправляется клиенту без преобразования имени восходящего потока nginx обратно на фактический сервер / домен. Таким образом, клиент получит следующее:

GET http://nginx.myserver.com/somedirectory
HTTP 301 Moved Permanently
...
Location: http://myproject:8000/somedirectory/

В myproject - это имя бэкэнда восходящего потока nginx. Это не реальный хост, который может разрешить клиент. Мне кажется, что вместо этого клиента следовало перенаправить на

http://nginx.myserver.com/somedirectory/  

Т.е. имя вышестоящего бэкэнда должно было быть заменено в заголовке ответа. Это ошибка в nginx или я что-то не так делаю?

Оказывается, у nginx довольно много прокси перенаправление варианты решения такого рода проблем. В итоге я использовал что-то вроде этого:

location / {
    proxy_pass  http://myproject;
    proxy_set_header Host myproject;
    proxy_redirect http://myproject/ $scheme://$host/;
    proxy_redirect http://myproject:8000/ $scheme://$host/;
}

Это в основном заменяет имя восходящего потока на $ host и удаляет порт. В моем случае это сработало, потому что я размещаю nginx на портах по умолчанию для HTTP / HTTPS. Если nginx работает на порту, отличном от порта по умолчанию, необходимо что-то вроде этого:

    proxy_redirect http://myproject/ $scheme://$host:$server_port/;
    proxy_redirect http://myproject:8000/ $scheme://$host:$server_port/;

Попробуйте использовать server_name_in_redirect как это:

server_name_in_redirect off;

Если это не сработает, возможно, вам придется что-то делать с proxy_redirect, хотя похоже, что ваш бэкэнд ведет себя правильно.