Nginx reverse proxy ทำให้เกิด 504 Gateway Timeout


131

ฉันใช้ Nginx เป็นพร็อกซีย้อนกลับที่รับคำขอจากนั้นใช้ proxy_pass เพื่อรับเว็บแอปพลิเคชันจริงจากเซิร์ฟเวอร์ต้นน้ำที่ทำงานบนพอร์ต 8001

หากฉันไปที่ mywebsite.com หรือทำ wget ฉันจะได้รับ 504 Gateway Timeout หลังจาก 60 วินาที ... อย่างไรก็ตามหากฉันโหลด 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

คำตอบ:


153

อาจเพิ่มอีกสองสามบรรทัดเพื่อเพิ่มระยะหมดเวลาไปยังต้นน้ำ ตัวอย่างด้านล่างกำหนดระยะหมดเวลาเป็น 300 วินาที:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;

5
ฉันคิดว่าการเพิ่มระยะหมดเวลาไม่ใช่คำตอบเว้นแต่คุณจะรู้ว่าเครือข่าย / บริการของคุณจะตอบสนองช้ามากเสมอหรือในบางกรณี คำขอเว็บเพียงไม่กี่รายการในปัจจุบันควรใช้เวลามากกว่าสองสามวินาทีเว้นแต่คุณจะดาวน์โหลดเนื้อหา (ไฟล์ / ภาพ)
Almund

@ อัลมุนด์ฉันคิดแบบเดียวกัน (แทบไม่ต้องกังวลกับการลองสิ่งนี้) แต่ไม่ว่าจะด้วยเหตุผลใดก็ตามสิ่งนี้ก็เหมาะกับฉัน (ก่อนหน้านี้หมดเวลาหลังจาก 60 วินาทีจะได้รับคำตอบทันที)
Dax Fohl

@Dax Fohl: อยากรู้จัง ฉันดึงแหล่งที่มาและดูอย่างรวดเร็วและจากสิ่งที่ฉันเห็นการตั้งค่า proxy_ ใด ๆ นอกเหนือจาก proxy_pass จะเริ่มต้นการตั้งค่ามากมายซึ่งฉันคิดว่าจะเรียกใช้พร็อกซีในลักษณะที่แตกต่างกันดังนั้นการตั้งค่าอะไรก็จะให้สิ่งนี้เหมือนกัน พฤติกรรม.
Almund

ไม่ได้แก้ปัญหาให้ฉันใช้มันกับเซิร์ฟเวอร์ nodejs
VPX

3
ฉันพบว่าฉันต้องการproxy_read_timeoutเมื่อทำการดีบักในแบ็กเอนด์เท่านั้น ขอบคุณ!
Jeff Puckett

82

การเพิ่มระยะหมดเวลาจะไม่สามารถแก้ปัญหาของคุณได้เนื่องจากดังที่คุณกล่าวไว้ว่าเว็บเซิร์ฟเวอร์เป้าหมายจริงตอบสนองได้ดี

ฉันมีปัญหาเดียวกันนี้และฉันพบว่ามันเกี่ยวข้องกับการไม่ใช้ 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


8
MONTHS ของปัญหาแก้ไขโดยบรรทัดเดียวproxy_set_header Connection "";ฮ่า ๆ อย่าใช้ runcloud
nodws

23

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ไม่ได้ทำอะไรฉันหวังว่าคำตอบนี้จะช่วยได้!


สวัสดีไม่มี timeout.conf ในไดเร็กทอรี config.d ของฉัน คุณบอกว่าสร้างมันและฉันต้องการยืนยันเพียงเพิ่มการตั้งค่าด้านบนใน timeout.conf?
tktktk0711

ใช่เพียงแค่เพิ่ม คุณสามารถปรับเปลี่ยนได้ตามความต้องการของคุณเอง แต่สิ่งเหล่านี้ใช้ได้ผลสำหรับฉัน!
Andreas Forslöw

น่าเสียดายที่ใน Laravel homestead กับ ubuntu และ Nginx สิ่งนี้ใช้ไม่ได้ :( คุณหมายถึงเพียงแค่เพิ่มบรรทัดเหล่านั้นโดยไม่มีserver{}หรืออย่างอื่นข้อผิดพลาดนี้เกิดขึ้นทันทีหลังจากผ่านไป 5 นาทีฉันโหลดซ้ำรีบูตและไม่เคยทำได้เกิน 5 นาทีหรือ 300 วินาทีมีแนวคิดเพิ่มเติมในการแก้ไข มัน?
Pathros

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 ไม่หมดเวลา

หากต้องการเพิ่มเวลา จำกัด สำหรับไซต์เดียวคุณสามารถแก้ไขเป็นกลุ่มได้ /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หรือหากคุณกำลังใช้นำรถไปจอดแล้วเพียงแค่พิมพ์


1
ขอบคุณที่ทำงานให้ฉัน:fastcgi_read_timeout 600; proxy_read_timeout 600;
Alejandro

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 ที่ส่งต่อ


1
คำตอบนี้คือทองคำสิ่งที่เกิดขึ้นกับฉัน ต้นน้ำชี้ไปที่ aws elb และการหมดเวลาของเกตเวย์ทันที
Nathan Do

2

มีปัญหาเดียวกัน ปรากฎว่าเกิดจากการติดตามการเชื่อมต่อ iptables บนเซิร์ฟเวอร์ต้นน้ำ หลังจากลบออก--state NEW,ESTABLISHED,RELATEDจากสคริปต์ไฟร์วอลล์และการล้างด้วยconntrack -Fปัญหาก็หายไป


0

NGINX เองอาจไม่ใช่สาเหตุที่แท้จริง

หากตั้งค่า "พอร์ตขั้นต่ำต่ออินสแตนซ์ VM" บนเกตเวย์ NAT ซึ่งอยู่ระหว่างอินสแตนซ์ NGINX ของคุณและproxy_passปลายทางมีขนาดเล็กเกินไปสำหรับจำนวนคำขอพร้อมกันก็จะต้องเพิ่มขึ้น

วิธีแก้ไข: เพิ่มจำนวนพอร์ตที่พร้อมใช้งานต่อ VM บน NAT Gateway

บริบทในกรณีของฉันบน Google Cloud พร็อกซีย้อนกลับ NGINX ถูกวางไว้ในซับเน็ตโดยมี NAT Gateway อินสแตนซ์ NGINX กำลังเปลี่ยนเส้นทางคำขอไปยังโดเมนที่เชื่อมโยงกับแบ็กเอนด์ API ของเรา (อัปสตรีม) ผ่าน NAT Gateway

เอกสารจาก GCPนี้จะช่วยให้คุณเข้าใจว่า NAT เกี่ยวข้องกับการหมดเวลาของ NGINX 504 อย่างไร


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.