Nginx was closing the client connection after exactly 60 seconds on requests like clip_video (ffmpeg, 5-40 min) because send_timeout and proxy_send_timeout both default to 60s. proxy_read_timeout was already 2100s but the other two timeouts were still at defaults. With proxy_buffering off, Nginx holds the write path to the client open as soon as the upstream connection is established. If the upstream sends no data for 60s (e.g. ffmpeg processing), Nginx treats the idle write path as stalled and closes the client connection, logging 499 (Client Closed Request). Fixed: raise proxy_send_timeout and send_timeout to 2100s to match proxy_read_timeout in the main location block. Also raised the Gunicorn default timeout from 30s to 120s in gunicorn_conf.py as a belt-and-suspenders measure (AE_API_GUNICORN_TIMEOUT env var takes precedence). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
221 lines
6.8 KiB
Plaintext
221 lines
6.8 KiB
Plaintext
map $http_upgrade $connection_upgrade {
|
|
default upgrade;
|
|
'' close;
|
|
}
|
|
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
|
|
server_name
|
|
${DOCKER_AE_API_SERVER_NAME}
|
|
~^(dev|test|bak|sr|prod)?-?(api|fastapi)\.oneskyit\.com$
|
|
api.localhost
|
|
fastapi.localhost
|
|
;
|
|
|
|
# server_name
|
|
# fastapi_gunicorn.localhost
|
|
# dev-api.localhost
|
|
# dev-api.oneskyit.com
|
|
# test-api.oneskyit.com
|
|
# ;
|
|
|
|
access_log /logs/nginx/access_fastapi_gunicorn.log;
|
|
error_log /logs/nginx/error_fastapi_gunicorn.log;
|
|
|
|
client_max_body_size ${OSIT_WEB_MAX_BODY_SIZE}; # 5120M; #4096M or 4G; 5120M or 5G;
|
|
|
|
location / {
|
|
# Based on recommendations here: https://www.uvicorn.org/deployment/#running-behind-nginx
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection $connection_upgrade;
|
|
|
|
proxy_redirect off;
|
|
proxy_buffering off;
|
|
|
|
# I think "X-Real-IP" might be needed for some things?
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
|
|
# This is needed for long running Python code. Default is 60 seconds
|
|
# Increased from 1200 to 1500 on 2022-04-17
|
|
# Increased from 1500 to 2000 on 2023-03-15
|
|
# Increased proxy read timeout to 2100 and decreased fastcgi options to 35s on 2023-03-16
|
|
# fastcgi_connect_timeout 4s;
|
|
# fastcgi_send_timeout 5s;
|
|
# fastcgi_read_timeout 5s;
|
|
|
|
# proxy read timeout being too low will cause 504 Gateway Time-out on the client browser
|
|
proxy_read_timeout 2100s;
|
|
# proxy_send_timeout and send_timeout default to 60s. For long-running endpoints
|
|
# (clip_video, ffmpeg operations that take 5-40 min), raise to match proxy_read_timeout.
|
|
proxy_send_timeout 2100s;
|
|
send_timeout 2100s;
|
|
|
|
proxy_pass http://fastapi_backend;
|
|
}
|
|
|
|
location /ws {
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
proxy_http_version 1.1;
|
|
|
|
proxy_redirect off;
|
|
proxy_buffering off;
|
|
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# proxy_read_timeout 600;
|
|
# proxy_headers_hash_max_size 1024;
|
|
|
|
proxy_pass http://fastapi_backend;
|
|
|
|
access_log /logs/nginx/access_fastapi_gunicorn_ws.log;
|
|
error_log /logs/nginx/error_fastapi_gunicorn_ws.log;
|
|
}
|
|
|
|
location /v3/ws {
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
proxy_http_version 1.1;
|
|
|
|
proxy_redirect off;
|
|
proxy_buffering off;
|
|
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
proxy_read_timeout 2100s;
|
|
|
|
proxy_pass http://fastapi_backend;
|
|
|
|
access_log /logs/nginx/access_fastapi_gunicorn_v3_ws.log;
|
|
error_log /logs/nginx/error_fastapi_gunicorn_v3_ws.log;
|
|
}
|
|
}
|
|
|
|
|
|
# server {
|
|
# listen 443 ssl;
|
|
# listen [::]:443 ssl;
|
|
# http2 on;
|
|
#
|
|
# server_name
|
|
# ${DOCKER_AE_API_SERVER_NAME}
|
|
# fastapi.localhost
|
|
# api.localhost
|
|
# localhost
|
|
# ;
|
|
#
|
|
# # server_name
|
|
# # fastapi_gunicorn.localhost
|
|
# # dev-api.localhost
|
|
# # dev-api.oneskyit.com
|
|
# # test-api.oneskyit.com
|
|
# # ;
|
|
#
|
|
# access_log /logs/nginx/access_fastapi_gunicorn.log;
|
|
# error_log /logs/nginx/error_fastapi_gunicorn.log;
|
|
#
|
|
# include /etc/nginx/options-ssl-nginx.conf;
|
|
#
|
|
# ssl_certificate /etc/certs/fullchain_wild.pem;
|
|
# ssl_certificate_key /etc/certs/privkey_wild.pem;
|
|
# ssl_dhparam /etc/certs/ssl-dhparams.pem;
|
|
#
|
|
# # include brotli.conf;
|
|
# # include gzip.conf;
|
|
#
|
|
# client_max_body_size ${OSIT_WEB_MAX_BODY_SIZE}; # 5120M; #4096M or 4G; 5120M or 5G;
|
|
#
|
|
# location / {
|
|
# # Based on recommendations here: https://www.uvicorn.org/deployment/#running-behind-nginx
|
|
# proxy_set_header Host $http_host;
|
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
# proxy_set_header X-Forwarded-Proto $scheme;
|
|
# proxy_set_header Upgrade $http_upgrade;
|
|
# proxy_set_header Connection $connection_upgrade;
|
|
#
|
|
# proxy_redirect off;
|
|
# proxy_buffering off;
|
|
#
|
|
# # I think "X-Real-IP" might be needed for some things?
|
|
# proxy_set_header X-Real-IP $remote_addr;
|
|
#
|
|
# # # This is needed for long running Python code. Default is 60 seconds
|
|
# # # Increased from 1200 to 1500 on 2022-04-17
|
|
# # # Increased from 1500 to 2000 on 2023-03-15
|
|
# # # Increased proxy read timeout to 2100 and decreased fastcgi options to 35s on 2023-03-16
|
|
# # fastcgi_connect_timeout 35s;
|
|
# # fastcgi_send_timeout 35s;
|
|
# # fastcgi_read_timeout 35s;
|
|
#
|
|
# # proxy read timeout being too low will cause 504 Gateway Time-out on the client browser
|
|
# proxy_read_timeout 2100s;
|
|
#
|
|
# proxy_pass http://fastapi_backend;
|
|
# }
|
|
#
|
|
# location /ws {
|
|
# proxy_set_header Host $http_host;
|
|
# proxy_set_header X-Real-IP $remote_addr;
|
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
# proxy_set_header X-Forwarded-Proto $scheme;
|
|
#
|
|
# proxy_http_version 1.1;
|
|
#
|
|
# proxy_redirect off;
|
|
# proxy_buffering off;
|
|
#
|
|
# proxy_set_header Upgrade $http_upgrade;
|
|
# proxy_set_header Connection "upgrade";
|
|
#
|
|
# # proxy_read_timeout 600;
|
|
# # proxy_headers_hash_max_size 1024;
|
|
#
|
|
# proxy_pass http://fastapi_backend;
|
|
#
|
|
# access_log /logs/nginx/access_fastapi_gunicorn_ws.log;
|
|
# error_log /logs/nginx/error_fastapi_gunicorn_ws.log;
|
|
# }
|
|
#
|
|
# location /v3/ws {
|
|
# proxy_set_header Host $http_host;
|
|
# proxy_set_header X-Real-IP $remote_addr;
|
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
# proxy_set_header X-Forwarded-Proto $scheme;
|
|
#
|
|
# proxy_http_version 1.1;
|
|
#
|
|
# proxy_redirect off;
|
|
# proxy_buffering off;
|
|
#
|
|
# proxy_set_header Upgrade $http_upgrade;
|
|
# proxy_set_header Connection "upgrade";
|
|
#
|
|
# proxy_read_timeout 2100s;
|
|
#
|
|
# proxy_pass http://fastapi_backend;
|
|
#
|
|
# access_log /logs/nginx/access_fastapi_gunicorn_v3_ws.log;
|
|
# error_log /logs/nginx/error_fastapi_gunicorn_v3_ws.log;
|
|
# }
|
|
# }
|
|
|
|
|
|
upstream fastapi_backend {
|
|
least_conn;
|
|
server ae_api:5005 weight=20 max_fails=1 fail_timeout=5s;
|
|
keepalive 10;
|
|
}
|