使用Nginx+uWSGI部署Django项目
使用Nginx+uWSGI部署Django项目
使用 Nginx + uWSGI 部署 Django 项目,核心是为 Django 应用提供一套 高性能、高稳定性、可扩展 的生产环境运行方案。Django 本身是一个 Python Web 框架,自带的开发服务器(runserver
)仅用于调试,无法应对高并发、安全防护等生产需求
一、核心作用:让 Django 能稳定跑在生产环境
Django 自带的 runserver
存在明显缺陷(单线程、无并发处理能力、无安全防护),无法直接用于生产。Nginx + uWSGI 的组合本质是 “分工协作” ,为 Django 搭建生产级运行架构:
- uWSGI:作为 “中间件”,负责将 Django 应用(Python 代码)与 Web 服务器(Nginx)连接。它能解析 Python 代码,处理 Django 的业务逻辑(如请求路由、数据库交互、模板渲染等),并将处理结果传递给 Nginx。
- Nginx:作为 “前端 Web 服务器”,直接面向用户浏览器 / 客户端,接收所有外部请求,再将 “需要 Django 处理的动态请求” 转发给 uWSGI,同时直接处理 “静态资源请求”(如图片、CSS、JS)。
二、具体能实现的关键功能
1. 处理高并发,提升访问性能
生产环境中,用户请求可能同时达到数百甚至数千次,Django 自带服务器完全无法承受,而 Nginx + uWSGI 通过 “多进程 / 多线程” 和 “请求分发” 实现高并发支持:
- uWSGI 的进程管理:可配置多进程(
workers
)、多线程(threads
),同时处理多个 Django 动态请求(例如配置 4 个 workers,每个 workers 对应 2 个线程,可同时处理 8 个并发请求),避免单线程阻塞。 - Nginx 的高并发能力:Nginx 基于 “事件驱动” 模型,能高效处理数万级的并发连接(远优于 Apache 等传统 Web 服务器),即使同时有大量用户访问,也能快速接收请求并分发,避免请求排队堵塞。
2. 直接处理静态资源,减轻 Django 负担
Django 处理静态资源(图片、CSS、JS、字体等)的效率极低,若所有请求都让 Django 处理,会严重占用其资源,导致动态业务响应变慢。Nginx 恰好擅长处理静态资源:
- 静态资源直出:通过 Nginx 配置,将
/static/
(Django 静态文件目录)、/media/
(用户上传文件目录)的请求直接拦截,由 Nginx 读取本地文件返回给用户,完全不经过 Django 和 uWSGI。 - 优化静态资源传输:Nginx 支持开启 Gzip 压缩(减小 CSS/JS 文件体积)、设置浏览器缓存(让用户第二次访问不重复下载静态资源),进一步提升静态资源加载速度。
3. 增强应用安全性,抵御常见攻击
生产环境中,Web 应用面临 XSS、CSRF、SQL 注入、端口暴露、恶意请求等安全风险,Nginx + uWSGI 可从多个层面加固防护:
- 隐藏后端技术栈:用户直接访问的是 Nginx(默认 80/443 端口),Django 和 uWSGI 运行在服务器内部端口(如 8000 端口,仅允许本地访问),外部无法直接探测到 Django 版本、Python 环境等信息,降低被针对性攻击的风险。
- 过滤恶意请求:通过 Nginx 配置,可拦截非法请求(如请求不存在的路径、携带恶意参数)、限制单 IP 访问频率(防止暴力破解)、禁止访问敏感文件(如
.git
目录、settings.py
配置文件)。 - 支持 HTTPS 加密:Nginx 可集成 SSL 证书(如 Let’s Encrypt 免费证书),开启 HTTPS 协议,加密用户与服务器之间的通信数据,防止数据被窃听或篡改(现代 Web 应用必须支持 HTTPS)。
4. 实现灵活的扩展与运维
随着项目规模增长,可能需要多服务器部署、负载均衡、灰度发布等需求,Nginx + uWSGI 的架构天然支持这些扩展场景:
- 负载均衡:当单个 Django 服务无法承受高并发时,可部署多台服务器运行相同的 Django + uWSGI 实例,由 Nginx 作为负载均衡器,将用户请求按策略(如轮询、权重)分发到不同服务器,实现 “横向扩展”,提升整体承载能力。
- 反向代理与多应用部署:一台服务器可通过 Nginx 配置,同时部署多个 Web 应用(如 Django 项目、Vue 前端项目、Node.js 项目),Nginx 根据请求的域名或路径(如
api.example.com
指向 Django,www.example.com
指向 Vue),将请求转发到对应的后端服务,实现 “一机多应用”。 - 日志与监控:Nginx 和 uWSGI 都支持详细的访问日志和错误日志,可记录用户请求信息(IP、时间、请求路径、响应状态码)、服务错误信息,便于运维人员排查问题;同时可集成监控工具(如 Prometheus + Grafana),实时监控服务的 CPU、内存占用、并发连接数等指标。
5. 保证服务稳定性,减少 downtime
生产环境要求服务 “7x24 小时” 稳定运行,Nginx + uWSGI 提供了多重保障机制:
- uWSGI 进程守护:可通过
supervisor
或systemd
工具管理 uWSGI 进程,一旦 uWSGI 崩溃或异常退出,工具会自动重启 uWSGI,确保 Django 服务不中断。 - Nginx 故障转移:在负载均衡场景下,若某台后端服务器(Django + uWSGI)故障,Nginx 会自动检测到该服务器不可用,将后续请求转发到其他正常服务器,避免单个服务器故障导致整体服务不可用。
三、总结:为什么必须用 Nginx + uWSGI?
简单来说,这套组合解决了 Django 从 “开发调试” 到 “生产运行” 的核心痛点:
需求场景 | Django 自带服务器(runserver) | Nginx + uWSGI 组合 |
---|---|---|
并发处理能力 | 单线程,仅支持 1-2 个请求 | 支持数千级并发,可横向扩展 |
静态资源处理 | 效率极低,占用业务资源 | 高效直出,支持压缩、缓存 |
安全性 | 无防护,暴露后端信息 | 隐藏端口、过滤恶意请求、支持 HTTPS |
稳定性 | 易崩溃,无自动恢复 | 进程守护、故障转移,7x24 运行 |
扩展性 | 无法扩展 | 支持负载均衡、多应用部署 |
因此,所有需要上线的 Django 项目,都必须通过 Nginx + uWSGI(或类似组合,如 Nginx + Gunicorn)部署,这是生产环境的标准方案。
配置:
安装或核对Python版本
which python3
ll /usr/bin/python*
安装
- 安装必要依赖
在安装Python3.6之前,需要确保系统具备必要的依赖包。运行以下命令:
yum -y install python3
输出以下内容
[root@localhost conf]# which python3
/usr/bin/which: no python3 in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
[root@localhost conf]# ll /usr/bin/python*
lrwxrwxrwx. 1 root root 7 6月 19 22:36 /usr/bin/python -> python2
lrwxrwxrwx. 1 root root 9 6月 19 22:36 /usr/bin/python2 -> python2.7
-rwxr-xr-x. 1 root root 7136 11月 6 2016 /usr/bin/python2.7
部署Nginx环境
运行安装脚本...
部署及测试uWSGI环境
yum install python3-devel -y #安装依赖环境
sudo pip3 install uwsgi #安装uwsgi
安装完成
[root@localhost ~]# sudo pip3 install uwsgi
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting uwsgiUsing cached https://files.pythonhosted.org/packages/6f/f0/d794e9c7359f488b158e88c9e718c5600efdb74a0daf77331e5ffb6c87c4/uwsgi-2.0.30.tar.gz
Installing collected packages: uwsgiRunning setup.py install for uwsgi ... done
Successfully installed uwsgi-2.0.30
执行以下命令,创建测试目录。
本示例以创建/home/myblog
目录为例,您可以根据需求自定义文件路径。
sudo mkdir /home/myblog
执行以下命令,创建并编辑测试程序文件test.py
。
cd /home/myblog
sudo vim test.py
输入a进入编辑模式,将以下内容复制到文件中。
def application(env, start_response):start_response('200 OK', [('Content-Type','text/html')])return [b"Hello World"]
执行以下命令启动
sudo /usr/local/bin/uwsgi --http :8001 --wsgi-file test.py
显示以下内容
[root@localhost myblog]# sudo /usr/local/bin/uwsgi --http :8001 --wsgi-file test.py
*** Starting uWSGI 2.0.30 (64bit) on [Mon Sep 15 20:14:44 2025] ***
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-44) on 15 September 2025 12:09:49
os: Linux-3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016
nodename: localhost.localdomain
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/myblog
detected binary path: /usr/local/bin/uwsgi
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 3782
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8001 fd 4
spawned uWSGI http 1 (pid: 25866)
uwsgi socket 0 bound to TCP address 127.0.0.1:45554 (port auto-assigned) fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
Python version: 3.6.8 (default, Nov 14 2023, 16:29:52) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
Python main interpreter initialized at 0x15f7930
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72920 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x15f7930 pid: 25865 (default app)
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 25865, cores: 1)
^C[root@localhost myblog]#
在本地电脑浏览器的地址栏输入<IP地址>:8001,访问测试文件。
curl 192.168.11.100:8001
Hello World[root@localhost ~]#
部署及测试Django环境
.执行以下命令,安装Django。
sudo pip3 install Django
安装成功后显示
Collecting typing-extensions; python_version < "3.8" (from asgiref<4,>=3.3.2->Django)Downloading https://files.pythonhosted.org/packages/45/6b/44f7f8f1e110027cf88956b59f2fad776cca7e1704396d043f89effd3a0e/typing_extensions-4.1.1-py3-none-any.whl
Installing collected packages: typing-extensions, asgiref, sqlparse, pytz, Django
Successfully installed Django-3.2.25 asgiref-3.4.1 pytz-2025.2 sqlparse-0.4.4 typing-extensions-4.1.1
.执行以下命令,创建项目。
本示例以创建项目文件uwsgi_project
为例,您可以根据需求自定义文件夹。
sudo /usr/local/bin/django-admin startproject uwsgi_project
或者
cd /home/myblog/
[root@localhost myblog]# django-admin startproject uwsgi_project
[root@localhost myblog]# ls
test.py uwsgi_project
执行以下命令,编辑settings.py
文件。
sudo vim /home/myblog/uwsgi_project/uwsgi_project/settings.py
将ALLOWED_HOSTS = [ ]
修改为ALLOWED_HOSTS = ["*"]
。修改完成后,按Esc
键,输入:wq
保存并退出文件。
说明
["*"]表示允许任何IP地址访问进来,否则访问会被拒绝,具体以您实际环境为准。
执行以下命令,启动Django环境。
cd /home/myblog/uwsgi_project
sudo python3 manage.py runserver 0.0.0.0:8002
如果出现以下类似报错:
django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17).
您可以将settings.py
文件中的DATABASES
注释掉,重新启动Django环境即可。修改settings.py
文件的具体操作,请参见编辑settings.py文件。
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
}
-
DATABASES
用于指定Django项目将要使用的数据库设置。本实例中未使用数据库,所以需要注释。 - 在实际项目中您可按需配置
在本地电脑浏览器的地址栏输入<IP地址>:8002,即可访问相关Django页面。
出现一个火箭...
配置Django的静态文件存放目录
指定静态文件存放目录
添加
STATIC_ROOT = BASE_DIR / 'static'
将django中默认静态文件存放到static目录中
cd /home/myblog/uwsgi_project
python3 manage.py collectstatic128 static files copied to '/home/myblog/uwsgi_project/static'.
[root@localhost uwsgi_project]#
配置Nginx、uWSGI、Django
1.如需配置Django,请在对应目录添加相关文件,具体以您部署的网站项目为准。本步骤仅用于展示基本的Django网页,请忽略此步骤。
2.执行以下命令,打开Nginx配置文件。
#Ubuntu
sudo vim /etc/nginx/sites-enabled/default#Centos
vim /usr/local/nginx/conf/nginx.conf
按i
键进入编辑模式,在server
中修改或添加以下参数。编辑完成后,按Esc
键,输入:wq
保存并退出文件。
upstream django {server 127.0.0.1:8001; #具体端口必须与您uWSGI配置文件中定义的端口一致}server {listen 80; #设置的nginx访问端口server_name test;charset utf-8;location /static {autoindex on;alias /home/myblog/uwsgi_project/static; #具体目录以您现场具体部署的目录为准}location / {uwsgi_pass 127.0.0.1:8001;include uwsgi_params; #具体目录以您现场具体部署的目录为准include /etc/nginx/uwsgi_params; #具体目录以您现场具体部署的目录为准uwsgi_param UWSGI_SCRIPT iCourse.wsgi; #具体目录以您现场具体部署的目录为准uwsgi_param UWSGI_CHDIR /iCourse; #具体目录以您现场具体部署的目录为准index index.html index.htm;client_max_body_size 35m;index index.html index.htm;}}
配置项 | 作用说明 |
---|---|
location / { ... } | 定义「匹配规则」:所有访问网站根路径(http://你的域名/ 或 http://IP/ )及其子路径(如 /login 、/article/1 )的请求,都由这个块内的规则处理。 |
uwsgi_pass 127.0.0.1:8001; | 核心转发规则:将匹配到的请求转发到本地(127.0.0.1 )的 8001 端口 —— 这正是 uWSGI 服务器监听的地址和端口(需确保 uWSGI 配置与此一致)。 |
include uwsgi_params; include /etc/nginx/uwsgi_params; | 加载 uWSGI 的「标准参数文件」:该文件定义了 Nginx 与 uWSGI 通信时需要传递的默认参数(如请求方法、路径、主机名等),确保两者能正确配合。(注:两行可能重复,保留其中一行指向正确路径即可) |
uwsgi_param UWSGI_SCRIPT iCourse.wsgi; | 告诉 uWSGI:Django 项目的「WSGI 入口文件」是 iCourse.wsgi 。(Django 项目创建后,会在项目目录下生成 项目名/wsgi.py 文件,这里的 iCourse.wsgi 即对应 iCourse/iCourse/wsgi.py ) |
uwsgi_param UWSGI_CHDIR /iCourse; | 告诉 uWSGI:Django 项目的「根目录」是 /iCourse (即 manage.py 所在的目录),uWSGI 会切换到这个目录下执行代码。 |
index index.html index.htm; | 定义「默认首页」:如果用户访问的是一个目录(如 /static/ ),Nginx 会优先寻找 index.html 或 index.htm 作为默认页面(此处对动态请求影响不大,主要是补充配置)。 |
client_max_body_size 35m; | 限制「客户端上传文件的最大大小」:允许用户上传不超过 35MB 的文件(避免大文件上传导致的问题)。 |
upstream paly {server 127.0.0.1:8001;#server 192.168.11.120;}server {listen 80;server_name localhost;#charset koi8-r;#access_log logs/host.access.log main;location /static {autoindex on;alias /home/myblog/uwsgi_project/static;}location / {uwsgi_pass 127.0.0.1:8001;include /usr/local/nginx/conf/uwsgi_params;uwsgi_param UWSGI_SCRIPT iCourse.wsgi; #具体目录以您现场具体部署的目录为准uwsgi_param UWSGI_CHDIR /iCourse; #具体目录以您现场具体部署的目录为准index index.html index.htm;client_max_body_size 35m;index index.html index.htm;}
执行以下命令,新建uWSGI配置文件uwsgi_config.ini
。
sudo vim uwsgi_config.ini
按i
键进入编辑模式,在文件中添加以下参数。编辑完成后,按Esc
键,输入:wq
保存并退出文件。
[uwsgi]
socket = 127.0.0.1:8001
chdir = /home/myblog/uwsgi_project/
wsgi-file = uwsgi_project/wsgi.py
processes = 4
threads = 2
vacuum = true
buffer-size = 65536
述参数配置说明如下所示:
- socket:此处的8001端口需要和nginx配置文件中定义的uwsgi_pass端口一致。
- chdir:指定项目目录,本示例中为
/home/myblog/uwsgi_project
,根据项目修改。 - wsgi-file:指定
Django's wsgi file
文件,根据项目修改。 - processes:最大工作进程。
- threads:每个工作进程processes启动后开启的线程个数。
- vacuum:环境退出时自动清理。
- buffer-size:设置用于uwsgi包解析的内部缓存区大小为64k,默认是4k。
启动程序。
执行以下命令,重启Nginx服务。
sudo systemctl restart nginx
执行以下命令,重启uWSGI服务。
1).执行以下命令,停止已启动的uWSGI程序。
ps aux |grep uwsgi
sudo kill -9 13187 #13187指通过上述命令获取的pid,具体pid以您现场实时获取的为准
执行以下命令,启动uWSGI服务。
sudo uwsgi --ini uwsgi_config.ini
/usr/local/bin/./uwsgi --ini uwsgi_config.ini
[uWSGI] getting INI configuration from uwsgi_config.ini
*** Starting uWSGI 2.0.30 (64bit) on [Mon Sep 15 21:32:10 2025] ***
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-44) on 15 September 2025 12:09:49
os: Linux-3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016
nodename: localhost.localdomain
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /root
detected binary path: /usr/local/bin/uwsgi
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
chdir() to /home/myblog/uwsgi_project/
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 3782
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 127.0.0.1:8001 fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
Python version: 3.6.8 (default, Nov 14 2023, 16:29:52) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
Python main interpreter initialized at 0x11eeca0
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 825016 bytes (805 KB) for 8 cores
*** Operational MODE: preforking+threaded ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x11eeca0 pid: 27461 (default app)
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (pid: 27461, cores: 2)
spawned uWSGI worker 2 (pid: 27463, cores: 2)
spawned uWSGI worker 3 (pid: 27464, cores: 2)
spawned uWSGI worker 4 (pid: 27465, cores: 2)
测试
firefox 127.0.0.1