Я использую nginx / 0.7.68, работающий на CentOS, со следующей конфигурацией:
server {
listen 80;
server_name ***;
index index.html index.htm index.php default.html default.htm default.php;
location / {
root /***;
proxy_pass http://***:8888;
index index.html index.htm;
}
# where *** is my variables
В proxy_pass
относится к записи DNS, IP-адрес которой часто меняется. Nginx кеширует устаревший IP-адрес, в результате чего запрашивается неправильный IP-адрес.
Как я могу запретить nginx кешировать IP-адрес, если он устарел?
Принятый ответ у меня не сработал на nginx / 1.4.2.
Использование переменной в proxy_pass
вызывает повторное разрешение имен DNS потому что NGINX обрабатывает переменные иначе, чем статическая конфигурация. Из NGINX proxy_pass
документация:
Значение параметра может содержать переменные. В этом случае, если адрес указан как доменное имя, имя ищется среди описанных групп серверов и, если не найдено, определяется с помощью преобразователя.
Например:
server {
...
resolver 127.0.0.1;
set $backend "http://dynamic.example.com:80";
proxy_pass $backend;
...
}
Примечание: преобразователь (то есть используемый сервер имен) ДОЛЖЕН быть доступен и настроен для его работы (и записи внутри /etc/hosts
файл не будет использоваться при поиске).
По умолчанию, версия 1.1.9 или более поздние версии кеша NGINX отвечают, используя значение TTL ответа. и необязательный valid
параметр позволяет переопределить время кеширования:
resolver 127.0.0.1 [::1]:5353 valid=30s;
Это интригующий вопрос, и, кстати, он не сработает. Вы можете попробовать использовать вверх по течению модуль и используйте директивы для аварийного переключения, чтобы увидеть, работает ли он как взлом.
Редактировать 2018: многое изменилось. Проверить ответ @ohaal чтобы получить реальную информацию об этом.
В комментариях gansbrest и ответе ohaal есть ценная информация.
Но я думаю, что важно упомянуть эту официальную статью о nginx, опубликованную в 2016 году, в которой четко объясняется поведение nginx по этому вопросу и возможные решения: https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
Нам действительно нужно «установить имя домена в переменной» и использовать решатель директива.
однако использование переменной изменяет поведение перезаписи. Возможно, вам придется использовать директиву rewrite, это зависит от вашего местоположения и настройки proxy_pass.
PS: хотел бы опубликовать комментарий, но пока недостаточно очков ...
Ответ ohaal приводит большинство из нас туда, но есть случай, когда DNS-преобразователь не находится на 127.0.0.1 (например, когда вы находитесь в специальной контейнерной среде)
В этом случае вы можете изменить конфигурацию nginx на resolver ${DNS_SERVER};
. Затем, прежде чем запускать nginx, запустите
export DNS_SERVER=$(cat /etc/resolv.conf |grep -i '^nameserver'|head -n1|cut -d ' ' -f2)
envsubst '${DNS_SERVER}' < your_nginx.conf.template > your_nginx.conf
Обратите внимание, что вам понадобится gettext
установлен пакет, поскольку он обеспечивает envsubst
команда.
Я собрал скрипт, чтобы следить за папкой conf.d на предмет изменений DNS и перезагружать nginx при обнаружении. Это первый проход, и его, безусловно, можно улучшить (на следующем проходе я буду использовать nginx -T специально для анализа восходящих потоков. Та же идея может быть использована для директив proxy_pass):
#!/bin/bash
get_upstreams() {
local files=$@
grep -hEo '(server\s+)[^:;]+' $files | cut -d' ' -f 2
}
resolve_hosts() {
local hosts=$@
for h in $hosts; do dig +short $h; done | sort -u
}
watch_dir=$1
[ -d $watch_dir ] || exit 2
upstreams=$(get_upstreams $watch_dir/*)
ips=$(resolve_hosts $upstreams)
if [ ! "$ips" ]; then
echo "Found no resolvable hosts in $watch_dir files."
fi
host_hash=$(echo $ips | /usr/bin/sha512sum)
echo $host_hash
echo $ips
while [ -d $watch_dir ]; do
sleep 30
upstreams=$(get_upstreams $watch_dir/*)
ips=$(resolve_hosts $upstreams)
new_hash=$(echo $ips | /usr/bin/sha512sum)
if [ "$host_hash" != "$new_hash" ]; then
echo Detected an upstream address change. $ips
echo Reloading nginx
echo $new_hash
echo $ips
/sbin/service nginx reload
host_hash=$new_hash
fi
done