Django+Nginx+uWSGI部署404问题排查指南 1. 问题现象与背景分析最近在部署Django项目时遇到了一个典型问题当通过NginxuWSGI组合访问Django应用时页面返回Not Found The requested resource was not found on this server错误。这个报错看似简单但实际上可能涉及Nginx配置、uWSGI参数、Django静态文件处理等多个环节的问题。这种情况通常发生在生产环境部署阶段特别是当开发者从Django自带的开发服务器runserver切换到NginxuWSGI组合时。开发服务器能正常访问的页面在生产环境下却出现404主要原因可能有Nginx未正确转发请求到uWSGIuWSGI与Django的WSGI接口配置有误Django的ALLOWED_HOSTS设置不匹配静态文件路径配置错误项目目录权限问题2. 环境准备与基础配置检查2.1 系统环境确认首先确保基础环境已经正确安装# 检查Python版本 python3 --version # 应显示3.6 # 检查Nginx状态 sudo systemctl status nginx # 应显示active (running) # 检查uWSGI是否安装 uwsgi --version # 应显示版本号2.2 Django项目结构验证典型的Django项目结构应如下/myproject /myproject __init__.py settings.py urls.py wsgi.py /static manage.py关键检查点确认wsgi.py文件存在且内容正确确保settings.py中DEBUGFalse生产环境检查ALLOWED_HOSTS[*]或包含你的域名3. Nginx配置深度解析3.1 核心配置参数正确的Nginx配置应该包含以下关键部分server { listen 80; server_name yourdomain.com; location /static/ { alias /path/to/your/project/static/; } location / { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; uwsgi_param Host $host; uwsgi_param X-Real-IP $remote_addr; } }3.2 常见配置错误排查uwsgi_pass地址不匹配检查Nginx中的uwsgi_pass与uWSGI配置的socket地址是否一致可以是unix socket如/tmp/uwsgi.sock或TCP端口如127.0.0.1:8001静态文件路径错误alias路径必须指向Django项目的static目录绝对路径确保执行过python manage.py collectstatic权限问题sudo chown -R www-data:www-data /path/to/your/project sudo chmod -R 755 /path/to/your/project4. uWSGI配置详解4.1 基础配置文件示例创建uwsgi.ini文件[uwsgi] chdir /path/to/your/project module project.wsgi:application master true processes 4 threads 2 socket /tmp/uwsgi.sock chmod-socket 666 vacuum true daemonize /var/log/uwsgi.log4.2 关键参数说明socket必须与Nginx配置中的uwsgi_pass对应chmod-socket设置正确的socket权限通常666daemonize建议指定日志文件便于排查问题module必须指向正确的WSGI入口点5. 完整问题排查流程5.1 分步验证法单独测试uWSGIuwsgi --http :8000 --module project.wsgi访问http://server:8000确认Django能否独立运行测试Nginx静态文件 在浏览器直接访问http://server/static/admin/css/base.css 确认能否看到静态文件内容检查uWSGI日志tail -f /var/log/uwsgi.log观察请求是否到达uWSGI5.2 常见错误解决方案错误现象可能原因解决方案502 Bad GatewayuWSGI未运行或socket权限不足检查uWSGI进程确认socket权限为666404 Not FoundURL路由不匹配或静态文件路径错误检查Django的urls.py和Nginx的static配置403 Forbidden文件系统权限不足递归修改项目目录权限为7556. 高级调试技巧6.1 日志详细配置在uWSGI配置中添加logto /var/log/uwsgi.log log-format %(addr) - %(user) [%(ltime)] %(method) %(uri) %(proto) %(status) %(size) %(referer) %(uagent) disable-logging false6.2 性能调优参数# 在uWSGI配置中添加 harakiri 30 # 请求超时时间(秒) max-requests 500 # 每个worker处理请求数后重启 buffer-size 65535 # 缓冲区大小7. 部署最佳实践使用虚拟环境python3 -m venv /path/to/venv source /path/to/venv/bin/activate pip install -r requirements.txt系统服务化 创建/etc/systemd/system/uwsgi.service[Unit] DescriptionuWSGI Emperor Aftersyslog.target [Service] ExecStart/path/to/venv/bin/uwsgi --ini /path/to/uwsgi.ini Restartalways KillSignalSIGQUIT Typenotify NotifyAccessall [Install] WantedBymulti-user.target静态文件处理优化location /static/ { alias /path/to/static/; expires 30d; access_log off; add_header Cache-Control public; }8. 典型问题案例解析案例某电商网站部署后出现404错误排查过程发现Nginx日志显示静态文件404检查发现collectstatic未执行执行后发现静态文件权限为root:root修正权限后问题依旧最终发现Nginx配置中alias路径多了一个斜杠# 错误配置 alias /path/to/static//; # 正确配置 alias /path/to/static/;经验总结配置文件中的路径斜杠要特别注意多余的斜杠可能导致路径解析失败。9. 安全加固建议关闭DEBUG模式# settings.py DEBUG False ALLOWED_HOSTS [yourdomain.com]隐藏Nginx版本信息server_tokens off;uWSGI隔离配置[uwsgi] uid www-data gid www-data定期更新组件sudo apt update sudo apt upgrade nginx uwsgi python310. 自动化部署方案使用Ansible实现一键部署# deploy_django.yml - hosts: webservers tasks: - name: Install dependencies apt: name: {{ item }} state: present with_items: - nginx - python3-pip - python3-venv - name: Create virtualenv command: python3 -m venv /opt/venv/project - name: Install requirements pip: requirements: /path/to/requirements.txt virtualenv: /opt/venv/project - name: Configure Nginx template: src: nginx.conf.j2 dest: /etc/nginx/sites-available/project notify: restart nginx - name: Configure uWSGI template: src: uwsgi.ini.j2 dest: /etc/uwsgi/sites/project.ini notify: restart uwsgi11. 性能监控与维护日志轮转配置sudo vim /etc/logrotate.d/uwsgi内容/var/log/uwsgi.log { daily missingok rotate 14 compress delaycompress notifempty create 640 www-data www-data sharedscripts postrotate [ -f /var/run/uwsgi.pid ] kill -HUP cat /var/run/uwsgi.pid endscript }监控关键指标# 查看uWSGI worker状态 uwsgi --connect-and-read /tmp/stats.sock # Nginx状态监控 sudo apt install nginx-module-status12. 容器化部署方案使用Docker Compose部署# Dockerfile FROM python:3.9 RUN apt-get update apt-get install -y nginx COPY . /app WORKDIR /app RUN pip install -r requirements.txt RUN python manage.py collectstatic --noinput COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 80 CMD service nginx start uwsgi --ini uwsgi.ini# docker-compose.yml version: 3 services: web: build: . ports: - 80:80 volumes: - ./static:/app/static restart: always13. 多环境配置管理使用环境变量管理不同环境配置# settings.py import os DEBUG os.getenv(DJANGO_DEBUG, False) True ALLOWED_HOSTS os.getenv(DJANGO_ALLOWED_HOSTS, ).split(,) STATIC_ROOT os.path.join(BASE_DIR, staticfiles)对应uWSGI配置[uwsgi] env DJANGO_DEBUGFalse env DJANGO_ALLOWED_HOSTSexample.com,www.example.com14. 高可用架构设计对于生产环境建议采用以下架构---------- | Load | | Balancer | --------- | ------------------------------ | | | -------------- ------------ ------------ | Web Server 1 | | Web Server 2 | | Web Server 3 | | Nginx uWSGI | | Nginx uWSGI| | Nginx uWSGI| --------------- ------------- ------------- | | | ----------------------------- | -------------- | Shared | | Storage | | (for static) | --------------15. 持续集成与部署GitLab CI示例配置# .gitlab-ci.yml stages: - test - deploy test: stage: test script: - python manage.py test deploy_prod: stage: deploy only: - master script: - ansible-playbook -i production deploy.yml16. 故障应急处理当出现严重故障时可按以下步骤处理快速回滚# 回退到上一个正常版本 git checkout HEAD~1 # 重启服务 sudo systemctl restart uwsgi nginx临时维护页面# 在Nginx配置中添加 error_page 502 503 504 /maintenance.html; location /maintenance.html { root /var/www/html; internal; }数据库备份恢复# 备份 python manage.py dumpdata backup.json # 恢复 python manage.py loaddata backup.json17. 扩展阅读与资源官方文档Nginx官方文档uWSGI文档Django部署指南性能优化Nginx调优worker_processes, worker_connectionsuWSGI调优processes, threads, harakiriDjango缓存Memcached, Redis安全加固HTTPS配置Lets Encrypt免费证书防火墙设置仅开放必要端口定期安全扫描使用lynis等工具18. 本地开发与生产环境差异处理常见差异及解决方案差异点开发环境生产环境解决方案DEBUG模式TrueFalse通过环境变量控制静态文件runserver自动处理需要collectstatic部署脚本中自动执行数据库SQLitePostgreSQL/MySQL多settings文件邮件发送控制台输出真实SMTP服务器配置分离实现方案# settings.py if os.getenv(ENVIRONMENT) production: from .settings_prod import * else: from .settings_dev import *19. 微服务架构下的部署调整当Django作为微服务的一部分时配置需要调整API网关集成location /api/ { proxy_pass http://django_upstream; proxy_set_header X-Real-IP $remote_addr; }uWSGI配置调整[uwsgi] http :8000 http-keepalive true健康检查端点# urls.py urlpatterns [ path(health/, lambda r: HttpResponse(OK)), ]20. 现代化部署方案演进Serverless部署使用Zappa部署到AWS Lambda使用Django-Serverless部署到Azure Functions边缘计算使用Cloudflare Workers处理静态内容边缘缓存动态内容静态站点生成使用Django-Bakery生成静态HTML结合CDN加速混合架构graph LR A[CDN] -- B[静态资源] A -- C[API Gateway] C -- D[Django微服务] C -- E[其他微服务]最后分享一个实际调试技巧当遇到难以诊断的404错误时可以临时在Django的urls.py最前面添加一个catch-all路由用于调试from django.http import HttpResponse urlpatterns [ path(, lambda request: HttpResponse(fRequested path: {request.path})), # ...其他正常路由 ]这样可以直接看到请求是否到达Django以及完整的请求路径帮助快速定位是Nginx路由问题还是Django路由问题。