Обратный прокси-сервер Nginx вызывает тайм-аут шлюза 504

130

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

Если я захожу на mywebsite.com или выполняю wget, то через 60 секунд я получаю таймаут шлюза 504 ... Однако, если я загружаю mywebsite.com:8001, приложение загружается должным образом!

Итак, что-то мешает Nginx взаимодействовать с вышестоящим сервером.

Все это началось после того, как моя хостинговая компания сбросила машину, на которой работали мои вещи, до этого никаких проблем не было.

Вот мой серверный блок vhosts:

server {
    listen   80;
    server_name mywebsite.com;

    root /home/user/public_html/mywebsite.com/public;

    access_log /home/user/public_html/mywebsite.com/log/access.log upstreamlog;
    error_log /home/user/public_html/mywebsite.com/log/error.log;

    location / {
        proxy_pass http://xxx.xxx.xxx.xxx:8001;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
} 

И вывод из моего журнала ошибок Nginx:

2014/06/27 13:10:58 [error] 31406#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xx.xxx.xxx, server: mywebsite.com, request: "GET / HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:8001/", host: "mywebsite.com"
Дэйв Рома
источник
На сервере запущен SELinux?
CrackerJack9
В МОЕМ СЛУЧАЕ проблемой был шлюз NAT, а не NGINX или серверный API. stackoverflow.com/a/62351959/9956279
Sushilinux

Ответы:

152

Возможно, можно добавить еще несколько строк, чтобы увеличить период ожидания для восходящего потока. В приведенных ниже примерах время ожидания устанавливается равным 300 секундам:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;
user2540984
источник
5
Я думаю, что увеличение тайм-аута редко является ответом, если вы не знаете, что ваша сеть / служба всегда или в некоторых случаях реагирует очень медленно. В настоящее время немногие веб-запросы должны занимать более нескольких секунд, если вы не загружаете контент (файлы / изображения)
Альмунд,
@Almund Я думал то же самое (почти не стал пытаться это сделать), но по какой-то причине это сработало для меня. (Ранее время ожидания истекало через 60 секунд, теперь ответ будет немедленно).
Dax Fohl
@ Дакс Фол: Любопытно. Я вытащил источник и быстро посмотрел, и, насколько я вижу, установка любого параметра proxy_, кроме proxy_pass, инициализирует кучу настроек, которые, как я полагаю, будут запускать прокси по-другому, поэтому, возможно, установка чего-либо даст то же самое поведение.
Almund
Не решил проблему для меня, используя его с сервером
nodejs
3
Я обнаружил, что мне нужен только proxy_read_timeoutпри отладке на бэкэнде. Спасибо!
Джефф Пакетт,
79

Увеличение тайм-аута вряд ли решит вашу проблему, поскольку, как вы говорите, фактический целевой веб-сервер отвечает нормально.

У меня была такая же проблема, и я обнаружил, что это связано с тем, что в соединении не используется keep-alive. Я не могу ответить, почему это так, но, очистив заголовок соединения, я решил эту проблему, и запрос был проксирован просто отлично:

server {
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://localhost:5000;
    }
}

Взгляните на эти сообщения, которые объясняют это более подробно: nginx закрывает восходящее соединение после запроса. Уточнение заголовка Keep-alive http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

Almund
источник
7
МЕСЯЦЫ проблем, решаемых одной строкой proxy_set_header Connection "";lol, не используйте runcloud
nodws
22

user2540984 , а также многие другие указали, что вы можете попробовать увеличить настройки времени ожидания. Я сам столкнулся с аналогичной проблемой и попытался изменить настройки тайм-аута в файле /etc/nginx/nginx.conf , как предлагают почти все в этих потоках. Однако это мне нисколько не помогло; в настройках тайм-аута NGINX не было явных изменений. После многих часов поиска мне наконец удалось решить мою проблему.

Решение находится в этой ветке форума , и в нем говорится, что вы должны поместить настройки тайм-аута в /etc/nginx/conf.d/timeout.conf (и если этот файл не существует, вы должны его создать). Я использовал те же настройки, что и в ветке:

proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;

Возможно, это не решение вашей конкретной проблемы, но если кто-то еще заметит, что изменения тайм-аута в /etc/nginx/nginx.conf ничего не делают, я надеюсь, что этот ответ поможет!

Андреас Форслёв
источник
привет, в моем каталоге config.d нет timeout.conf. Вы сказали создать его, и я хочу подтвердить, что просто добавьте вышеуказанный параметр в timeout.conf?
tktktk0711
Да просто добавьте их. Вы можете изменить их для своих нужд, но у меня это сработало!
Андреас Форслёв
К сожалению, в усадьбе Laravel с ubuntu и Nginx это не работает. :( Вы хотите просто добавить эти строки? Без server{}или что-то еще? Эта ошибка появляется сразу через 5 минут. Я перезагружаю, перезагружаюсь, и она никогда не проходит дольше этих 5 минут или 300 секунд. Есть еще идеи для исправления это?
Патрос
15

Если вы хотите увеличить или добавить ограничение по времени для всех сайтов, вы можете добавить в nginx.confфайл следующие строки.

Добавьте строки ниже в httpраздел /usr/local/etc/nginx/nginx.confили /etc/nginx/nginx.confфайл.

fastcgi_read_timeout 600;
proxy_read_timeout 600;

Если вышеуказанных строк нет в confфайле, добавьте их, в противном случае увеличьте fastcgi_read_timeoutи proxy_read_timeoutубедитесь, что у nginx и php-fpm не истекло время ожидания.

Чтобы увеличить ограничение по времени только для одного сайта, вы можете редактировать в vim /etc/nginx/sites-available/example.com

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
        fastcgi_pass  unix:/var/run/php5-fpm.sock;
    fastcgi_read_timeout 300; 
}

и после добавления этих строк nginx.confне забудьте перезапустить nginx.

service php7-fpm reload 
service nginx reload

или, если вы пользуетесь услугами камердинера, просто введите valet restart.

Adeel
источник
1
Спасибо, у меня работает:fastcgi_read_timeout 600; proxy_read_timeout 600;
Алехандро
13

Вы также можете столкнуться с этой ситуацией, если ваш вышестоящий сервер использует доменное имя и его IP-адрес изменяется (например, ваш вышестоящий сервер указывает на AWS Elastic Load Balancer).

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

Вы можете указать nginx использовать сервер имен для повторного разрешения домена после истечения срока действия кэшированной записи:

location /mylocation {
    # use google dns to resolve host after IP cached expires
    resolver 8.8.8.8;
    set $upstream_endpoint http://your.backend.server/;
    proxy_pass $upstream_endpoint;
}

Документы на proxy_pass объясняют, почему этот трюк работает:

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

Престижность "Nginx с динамическими восходящими потоками" (tenzer.dk) за подробное объяснение, которое также содержит некоторую важную информацию об оговорках этого подхода в отношении перенаправленных URI.

el.atomo
источник
1
этот ответ - золото, именно это и случилось со мной. восходящий поток указывает на aws elb и внезапный тайм-аут шлюза.
Натан До
2

Была такая же проблема. Оказалось, это было вызвано отслеживанием подключения iptables на вышестоящем сервере. После удаления --state NEW,ESTABLISHED,RELATEDиз брандмауэра скрипта и прошивки conntrack -Fпроблема исчезла.

Mindlab
источник
0

Сам NGINX не может быть основной причиной.

ЕСЛИ «минимальное количество портов на экземпляр виртуальной машины», установленное на шлюзе NAT, которое стоит между вашим экземпляром NGINX и proxy_passместом назначения, слишком мало для количества одновременных запросов, его необходимо увеличить.

Решение. Увеличьте доступное количество портов на каждую виртуальную машину на шлюзе NAT.

Контекст В моем случае в Google Cloud обратный прокси-сервер NGINX был размещен внутри подсети со шлюзом NAT. Экземпляр NGINX перенаправлял запросы в домен, связанный с нашим внутренним API (восходящим потоком), через шлюз NAT.

Эта документация от GCP поможет вам понять, какое отношение NAT имеет к таймауту NGINX 504.

Sushilinux
источник
-1

В моем случае я перезапускаю php, и все становится нормально.

Махди Аслами
источник