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

Динамические бэкенды с HAProxy

Я пытаюсь найти лучший способ обработки динамического проксирования HTTP-запросов.

В основном я хочу взять динамическое имя хоста в виде myname.cust.mydomain.example а затем перенаправить запросы на внутренний сервер HTTP с именем «myname», взятым из имени хоста.

Я ломал голову, пытаясь выяснить, как лучше всего справиться с этим, и справится ли HAProxy с этой задачей.

Другой вариант, о котором я подумал, - это что-то вроде Lighttpd с LUA или даже Nginx.

Самым простым решением было бы просто использовать DNS для сопоставления foo.cust.mydomain.example к определенному IP-адресу сервера, как предложил womble. Это пропустит весь прокси-сервер. Возможно, это невозможно для вас, например, если у вас нет общедоступных IP-адресов для внутренних серверов.

Направление всех запросов на один сервер (с подстановочным знаком DNS) с последующей динамической пересылкой запросов в соответствии с заголовком Host немного сложнее, и кажется, что HAProxy не может этого сделать, потому что каждый внутренний сервер должен быть явно определен в конфигурации HAProxy.

Однако Nginx отличается: при правильной настройке Nginx может использовать заголовок Host для выбора серверной части. Конечно, Nginx нужен DNS-сервер, который сопоставляет имена с внутренними адресами.

Вот небольшой пример конфигурации:

server {
    listen 80 default;

    location / {
        # You might need to send some headers to the backend server
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        resolver 192.0.2.1; # DNS server IP
        # Forward all requests to the backend server using $http_host
        # (this is the 'Host:' header value)
        proxy_pass http://$http_host$request_uri;
    }
}

Это перенаправляет http://myserver.cust.mydomain.example/foo/ к http://myserver.cust.mydomain.example/foo/. На первый взгляд это не кажется очень полезным. Но если вы настраиваете частный DNS-сервер, который сопоставляет эти имена с адресами внутреннего сервера, запрос фактически пересылается на правильный внутренний сервер по частному адресу.

Но такая настройка DNS-сервера может быть нежелательной и в некоторых случаях может вызвать проблемы. Итак, с некоторыми дополнениями к конфигурации Nginx мы можем использовать другой подход:

location / {
    # headers...

    resolver 192.0.2.1;

    # A regex to get the first part (hostname) from the Host header
    if ($http_host ~* "([a-z0-9-]+)(\.[a-z0-9-]+)*") {
        # Save a captured part from the regex to a variable
        set $redirect_hostname $1;
        # Pass the request to a desired backend
        proxy_pass   http://$redirect_hostname.private.mydomain.example$request_uri;
    }
}

Теперь перенаправление идет с http://myserver.cust.mydomain.example/foo/ к http://myserver.private.mydomain.example/foo/. DNS-сервер может содержать частные адреса в другом домене и proxy_pass директиву можно изменить в соответствии с желаемой конфигурацией сервера имен.

Я все еще думаю, что такой вид проксирования может быть не самым простым способом решить всю картину, но в конце концов это одна из возможностей. Я счастлив, если это помогло.

Ссылки: Nginx вики, особенно HttpProxyModule и HttpRewriteModule