如何修复AWS ECS上Django应用的504 Gateway Time-out问题?
问题描述
在AWS ECS上部署Django应用,采用Nginx+Gunicorn架构,频繁出现499状态码,随后触发504超时错误。出现问题时后端数分钟无响应,重启容器后恢复正常。
相关日志
2023/09/06 14:42:52 [error] 9#9: *1348 upstream timed out (110: Operation timed out) while reading response header from upstream, client: 10.0.10.112, server: , request: "GET /api/tasks/logs/8b9ad2d4-b63a-4782-83c2-940764c04eb1/ HTTP/1.1", upstream: "http://127.0.0.1:8000/api/tasks/logs/8b9ad2d4-b63a-4782-88c2-940764u04eb1/", host: "admin.myapp.com" 10.0.11.207 - - [06/Sep/2023:14:42:48 +0000] "GET /admin HTTP/1.1" 499 0 "-" "ELB-HealthChecker/2.0" "-" 10.0.10.112 - - [06/Sep/2023:14:42:49 +0000] "GET /admin HTTP/1.1" 504 167 "-" "ELB-HealthChecker/2.0" "-"
环境与配置信息
upstream myapp_backend { server ${APP_HOST}:8000; } server { listen 80; location / { proxy_pass http://myapp_backend; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; client_max_body_size 200M; } location /static/ { alias /home/app/web/static/; } }
- Nginx Dockerfile:
FROM public.ecr.aws/nginx/nginx:1.24-alpine RUN rm /etc/nginx/conf.d/default.conf COPY nginx.conf /nginx.conf.template CMD ["/bin/sh" , "-c" , "envsubst '$APP_HOST' < /nginx.conf.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"] EXPOSE 80
已调整健康检查默认设置并延长目标组超时时间,问题仍每日出现2-3次,需排查原因并提供修复方案。
排查与修复方案
可能原因
Nginx与Gunicorn超时不匹配
当前Nginx未配置代理超时参数,默认超时时间较短(通常60s),若Gunicorn处理请求耗时超过该值,会触发上游超时,进而导致ELB健康检查主动断开连接(499),最终触发504。Django接口阻塞
日志中/api/tasks/logs/接口超时,该接口可能因处理大量日志数据时发生阻塞(如慢SQL查询、文件IO等待),占用Gunicorn worker资源,导致无法响应后续健康检查请求。Gunicorn进程异常
即使资源使用率低,若worker数量不足,单个阻塞请求会占满所有worker;或worker进程因异常僵死,无法处理新请求。容器间通信问题
Nginx与Gunicorn容器间的网络连接可能出现间歇性中断,导致Nginx无法连接上游服务。
修复方案
1. 调整Nginx代理超时参数
在location /块中添加超时配置,确保与ELB、Gunicorn的超时逻辑匹配:
location / { proxy_pass http://myapp_backend; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; client_max_body_size 200M; # 新增超时配置 proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; proxy_buffering off; }
proxy_read_timeout建议设置为比ELB健康检查超时更长的时间,避免Nginx先于ELB断开连接。
2. 优化阻塞接口
- 针对
/api/tasks/logs/:- 检查数据库查询,添加必要索引优化查询速度;
- 改用异步框架(如Celery)处理日志加载逻辑,避免同步请求阻塞worker;
- 实现分页返回日志,减少单次请求的数据量。
3. 优化Gunicorn配置
- 调整worker数量:建议设置为
2 * CPU核心数 + 1,保证有足够worker处理并发; - 添加超时参数:
--timeout 300,让Gunicorn自动重启超时的worker; - 启用进程自动重启:
--max-requests 1000,避免worker因内存泄漏或异常僵死。
4. 优化健康检查
- 改用轻量健康检查端点:比如专门的
/health/接口(可通过django-health-check库实现),避免使用/admin这类资源消耗大的路径; - 调整健康检查参数:间隔设为10s,超时设为5s,失败阈值3,成功阈值2,减少误判。
5. 排查容器通信问题
- 验证Nginx容器能否正常访问Gunicorn的8000端口;
- 在Nginx中添加连接日志,记录与Gunicorn的连接状态;
- 采用ECS服务发现或静态IP配置,避免容器IP变化导致的连接异常。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

