Nginx не запустится с хоста, не найденного в апстриме - PullRequest
0 голосов
/ 09 мая 2018

Я использую nginx для прокси и поддерживаю постоянные соединения с удаленными серверами для меня.

Я настроил около 15 блоков, похожих на этот пример:

upstream rinu-test {
    server test.rinu.test:443;
    keepalive 20;
}
server {
    listen 80;
    server_name test.rinu.test;
    location / {
        proxy_pass https://rinu-test;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $http_host;
    }
}

Проблема в том, что если имя хоста не может быть разрешено в одном или нескольких блоках upstream, nginx не будет (пере) запускаться. Я также не могу использовать статические IP-адреса, некоторые из этих хостов явно сказали не делать этого, потому что IP-адреса изменятся. Любое другое решение, которое я видел в этом сообщении об ошибке, говорит, что нужно избавиться от upstream и сделать все в блоке location. Это невозможно здесь, потому что keepalive доступно только под upstream.

Я могу временно позволить себе потерять один сервер, но не все 15.

Edit: Оказывается, nginx не подходит для этого варианта использования. Следует использовать альтернативный серверный прокси-сервер поддержки. Пользовательская альтернатива Node.js находится в мой ответ . Пока что я не нашел других альтернатив, которые действительно работают.

Ответы [ 5 ]

0 голосов
/ 16 мая 2018

Альтернатива - написать новый сервис, который делает только то, что я хочу. Следующее заменяет nginx для проксирования соединений https с использованием Node.js

const http = require('http');
const https = require('https');

const httpsKeepAliveAgent = new https.Agent({ keepAlive: true });

http.createServer(onRequest).listen(3000);

function onRequest(client_req, client_res) {
    https.pipe(
        protocol.request({
            host: client_req.headers.host,
            port: 443,
            path: client_req.url,
            method: client_req.method,
            headers: client_req.headers,
            agent: httpsKeepAliveAgent
        }, (res) => {
            res.pipe(client_res);
        }).on('error', (e) => {
            client_res.end();
        })
    );
}

Пример использования: curl http://localhost:3000/request_uri -H "Host: test.rinu.test" что эквивалентно: curl https://test.rinu.test/request_uri

0 голосов
/ 15 мая 2018

Я установил параметр разрешения на сервере, и вам нужно установить Nginx Resolver в nginx.conf, как показано ниже:

/ и т.д. / Nginx / nginx.conf:

http {
    resolver 192.168.0.2 ipv6=off valid=40s;  # The DNS IP server
} 

Site.conf:

upstream rinu-test {
    server test.rinu.test:443;
    keepalive 20;
}
0 голосов
/ 14 мая 2018

Одним из возможных решений является использование локального кэша DNS. Это может быть локальный DNS-сервер, такой как Bind или Dnsmasq (с некоторой хитрой конфигурацией, обратите внимание, что nginx может также использовать указанный DNS-сервер вместо системного по умолчанию) или просто поддерживать кэш в файле hosts .

Кажется, что использование hosts файла с некоторыми сценариями - довольно простой способ. Файл hosts должен быть разбит на статическую и динамическую части (т. Е. cat hosts.static hosts.dynamic > hosts), а динамическая часть должна автоматически генерироваться (и обновляться) скриптом.

Возможно, имеет смысл время от времени проверять имена хостов на предмет изменения IP-адресов, обновлять файл хостов и перезагружать конфигурацию в nginx при изменениях. В случае, если какое-либо имя хоста не может быть разрешено, следует использовать старый IP-адрес или какой-либо IP-адрес по умолчанию (например, 127.0.1.9).

Если вам не нужны имена хостов в конфигурационном файле nginx (т. Е. Достаточно IP-адресов), сценарий upstream с IP-адресами (разрешенными именами хостов) может быть сгенерирован скриптом, и включает в Конфигурация nginx - и в этом случае не нужно трогать файл hosts.

0 голосов
/ 15 мая 2018

Ваш сценарий очень похож на тот, когда используется aws ELB в качестве восходящих потоков, где resolve необходим правильный IP-адрес определенного домена.

Первое, что вам нужно сделать и убедиться, чтоявляется то, что DNS-серверы, которые вы используете, могут разрешать ваши домены, тогда вы можете создать свою конфигурацию следующим образом:

resolver 10.0.0.2 valid=300s;
resolver_timeout 10s;

location /foo {
    set $foo_backend_servers foo_backends.example.com;
    proxy_pass http://$foo_backend_servers;
 }

location /bar {
    set $bar_backend_servers bar_backends.example.com;
    proxy_pass http://$bar_backend_servers;
 }

Обратите внимание, resolver 10.0.0.2 это должен быть IP-адрес DNS-сервера, который работает, и ответить на вашзапросы, в зависимости от вашей настройки, это может быть служба локального кэша, например unbound .а затем просто используйте resolve 127.0.0.1

Теперь очень важно использовать переменную для указания имени домена из документов:

Когда вы используетепеременная для указания имени домена в директиве proxy_pass, NGINX повторно разрешает имя домена после истечения его TTL.

Вы можете проверить свой преобразователь, используя такие инструменты, как dig, например:

$ dig +short stackoverflow.com

В случае, если необходимо использовать keepalive в восходящем потоке, а если нет возможности использовать Nginx +, то вы можете попробовать openresty балансировщик , вы будетенужно использовать / внедрить lua-resty-dns

0 голосов
/ 12 мая 2018

Более ранние версии nginx (до 1.1.4), которая уже использовала огромное количество самых посещаемых веб-сайтов во всем мире (а некоторые до сих пор работают даже в наши дни, если верить заголовкам серверов), даже не поддерживали keepalive на стороне upstream, потому что это очень мало выгодно в настройках центра обработки данных, если только у вас нет нетривиальной задержки между вашими различными хостами; см. https://serverfault.com/a/883019/110020 для некоторых объяснений.

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

(Обратите внимание, что ваше текущее решение также неверно, потому что изменение IP-адреса также останется незамеченным, потому что вы выполняете разрешение имени хоста только при перезагрузке конфигурации; поэтому, даже если nginx запустится, он в основном перестанет работать как только IP-адреса вышестоящих серверов меняются.)

Потенциальные решения, выберите одно:

  • Лучшее решение, по-видимому, состоит в том, чтобы просто избавиться от upstream keepalive, который, вероятно, не нужен в среде центра обработки данных, и использовать переменные с proxy_pass для современной DNS разрешение для каждого запроса (nginx все еще достаточно умен, чтобы выполнять кэширование таких разрешений)

  • Другой вариант - получить платную версию nginx через коммерческую подписку, которая имеет параметр resolve для директивы server в контексте upstream.

  • Наконец, еще одна попытка может заключаться в использовании set переменной и / или map для указания серверов в upstream; это ни подтверждено, ни опровергнуто не было выполнено; например, это может или не может работать.

...