华为云ECS云服务器部署Django网站:uWSGI+Nginx全套配置代码与实战指南
1. 引言:为什么选择华为云ECS + Nginx + uWSGI部署Django
Django作为Python生态中最成熟、最全面的Web框架,凭借其"batteries-included"的设计理念深受开发者喜爱。然而,Django自带的开发服务器runserver仅适用于本地调试场景,不具备生产环境所需的并发处理能力、安全性和稳定性。将Django应用部署至生产环境,需要借助专业的应用服务器与Web服务器构建分层架构。
uWSGI是一个实现了WSGI协议的应用服务器,它负责将Nginx转发的请求翻译成Django项目能够处理的格式,并调用Django的WSGI接口执行业务逻辑。Nginx则作为反向代理服务器置于uWSGI前端,负责处理静态资源请求、负载均衡、SSL终止以及抵御部分恶意流量。华为云弹性云服务器ECS提供了灵活、可扩展的计算资源,结合其稳定的网络环境和丰富的镜像源支持,是部署Django生产应用的理想选择。
需要先登录华为云控制台,点击:华为云控制台,还没有账号,点击:注册并关联,已有账号点击:登录后关联
2. Nginx + uWSGI + Django三层架构原理解析
2.1 分层架构概述
一套完整的Django生产部署架构由以下三层组成:
- Nginx(前端Web服务器):负责接收客户端的HTTP请求,处理静态资源(CSS、JavaScript、图片等),并将动态请求转发给后端的uWSGI服务。
- uWSGI(应用服务器):作为Django与Nginx之间的桥梁,通过WSGI协议调用Django应用,处理动态内容生成。
- Django(后端应用):实际处理业务逻辑、数据库交互、模板渲染等核心功能。
2.2 请求流转过程
用户请求的完整流转路径如下:浏览器发起HTTP请求 → 经过域名解析到达ECS的公网IP → Nginx监听80/443端口接收请求 → Nginx判断请求类型:若请求静态资源则直接返回,若为动态请求则通过uWSGI协议转发给uWSGI服务 → uWSGI调用Django的WSGI接口处理请求 → Django生成响应内容并逐层返回给用户。
2.3 分层架构的核心优势
这种分层设计带来了三大核心价值:
- 性能优化:uWSGI通过多进程/多线程模型大幅提升并发处理能力,Nginx的异步非阻塞IO架构可轻松处理数万并发连接。
- 安全隔离:Nginx作为前端防护层,可以有效阻断SQL注入、XSS攻击等常见Web威胁,同时隐藏后端服务的具体细节。
- 资源效率:静态资源由Nginx直接返回,完全不占用Django应用进程的资源,让Django专注于动态内容的处理,实现动静分离。
3. 华为云ECS环境准备
3.1 购买ECS实例
登录华为云控制台后,进入弹性云服务器ECS产品页面,点击"购买弹性云服务器"。在配置选择上,建议关注以下几点:
- 区域选择:选择距离目标用户群体最近的地域,以降低网络延迟。国内用户通常选择华东-上海或华南-广州。
- 计费模式:生产环境建议选择包年/包月以获得更优价格;测试或学习用途可选择按需计费,灵活按量付费。
- 镜像选择:推荐使用Ubuntu 22.04 LTS或华为云自研的Huawei Cloud EulerOS 2.0。本文示例基于Ubuntu 22.04 LTS。
- 规格配置:小型项目至少2核4GB内存起步,中型项目建议4核8GB,根据预期访问量适当升级。
- 弹性公网IP:购买时务必绑定弹性公网IP(EIP),否则无法从公网访问。
3.2 安全组规则配置
安全组是华为云的重要网络安全隔离手段,必须在ECS所属的安全组中开放必要的端口。以下是Django部署必需的安全组规则:
| 方向 | 优先级 | 策略 | 类型 | 协议端口 | 源地址 | 说明 |
|---|---|---|---|---|---|---|
| 入方向 | 1 | 允许 | IPv4 | TCP: 22 | 0.0.0.0/0 | SSH远程连接 |
| 入方向 | 1 | 允许 | IPv4 | TCP: 80 | 0.0.0.0/0 | HTTP网站访问 |
| 入方向 | 1 | 允许 | IPv4 | TCP: 443 | 0.0.0.0/0 | HTTPS网站访问(可选) |
| 入方向 | 1 | 允许 | IPv4 | TCP: 8001-8003 | 0.0.0.0/0 | uWSGI测试与调试端口(可选) |
配置方法:登录华为云控制台,进入"虚拟私有云 VPC" → "安全组" → 选择ECS所在的安全组 → "入方向规则" → "添加规则",按上述端口列表逐一添加。
3.3 更新镜像源与系统软件
为了更好地获取和更新系统软件,建议将镜像源更新为华为云镜像源,可显著提升软件包的下载速度。执行以下命令:
sudo apt update
sudo apt upgrade -y4. Python环境与项目部署
4.1 检查Python版本
首先确认ECS自带的Python版本是否与本地Django项目兼容:
which python3
python3 --version如果版本不匹配,需要安装指定版本的Python。以Python 3.10为例:
sudo apt install build-essential libssl-dev zlib1g-dev libncurses5-dev \
libgdbm-dev libnss3-dev libreadline-dev libffi-dev -y4.2 创建Python虚拟环境
生产环境部署强烈建议使用虚拟环境,避免项目依赖与系统Python包发生冲突。执行以下命令:
# 安装venv模块
sudo apt install python3-venv -y
# 创建项目目录
sudo mkdir -p /var/www/myproject
cd /var/www/myproject
# 创建虚拟环境
python3 -m venv venv
# 激活虚拟环境
source venv/bin/activate4.3 上传Django项目代码
将本地Django项目代码上传到服务器。可以使用Git克隆、SCP或FTP等方式:
# 方式一:使用Git克隆(推荐)
git clone https://github.com/yourusername/myproject.git .
# 方式二:使用SCP上传
scp -r /path/to/local/myproject root@服务器IP:/var/www/myproject/4.4 安装项目依赖
在虚拟环境中安装项目所需的所有依赖包:
# 确保虚拟环境已激活
source /var/www/myproject/venv/bin/activate
# 安装依赖
pip install -r requirements.txt
# 如果项目没有requirements.txt,可手动生成:
# pip freeze > requirements.txt4.5 配置Django生产环境设置
修改Django项目的settings.py文件,进行生产环境配置:
# settings.py
# 关闭调试模式
DEBUG = False
# 配置允许访问的主机
ALLOWED_HOSTS = ['你的域名', '服务器公网IP']
# 静态文件收集目录
STATIC_ROOT = '/var/www/myproject/static/'
STATIC_URL = '/static/'
# 媒体文件目录
MEDIA_ROOT = '/var/www/myproject/media/'
MEDIA_URL = '/media/'4.6 执行数据库迁移
python manage.py migrate4.7 收集静态文件
生产环境下必须由Web服务器(如Nginx)来高效地托管CSS、JavaScript、图片等静态资源。collectstatic命令正是连接Django应用与Web服务器静态文件目录的桥梁:
python manage.py collectstatic --noinput执行后,所有静态文件将被收集到STATIC_ROOT指定的目录中。
5. uWSGI安装与配置
5.1 安装uWSGI
在虚拟环境中安装uWSGI:
source /var/www/myproject/venv/bin/activate
pip install uwsgi5.2 创建uWSGI配置文件
在项目根目录下创建uwsgi.ini配置文件:
sudo vim /var/www/myproject/uwsgi.ini配置文件内容如下:
[uwsgi]
# 项目目录
chdir = /var/www/myproject
# Django的WSGI模块
module = myproject.wsgi:application
# 虚拟环境路径
home = /var/www/myproject/venv
# 进程和线程配置
master = true
processes = 4
threads = 2
# Socket文件(与Nginx通信)
socket = /var/www/myproject/myproject.sock
# Socket文件权限
chmod-socket = 666
# 进程ID文件
pidfile = /var/www/myproject/uwsgi.pid
# 日志文件
daemonize = /var/www/myproject/uwsgi.log
# 自动回收请求
max-requests = 5000
# 内存清理
harakiri = 60
# 缓冲请求
buffer-size = 32768
# 禁用日志时间戳(可选)
disable-logging = false
# 环境变量(可选)
env = DJANGO_SETTINGS_MODULE=myproject.settings配置参数说明:
- chdir:指向项目根目录(manage.py所在位置)
- module:项目名.wsgi:application,指定Django的WSGI入口
- home:虚拟环境的Python解释器路径
- processes:工作进程数量,建议设置为CPU核心数的1-2倍
- threads:每个进程的线程数
- socket:Unix Socket文件路径,用于与Nginx通信
- daemonize:将uWSGI进程转为后台运行并记录日志
5.3 测试uWSGI是否正常工作
使用以下命令测试uWSGI能否正常启动Django应用:
uwsgi --ini /var/www/myproject/uwsgi.ini如果配置正确,uWSGI会以后台进程方式运行,并将日志写入uwsgi.log文件。
6. Nginx安装与配置
6.1 安装Nginx
sudo apt install nginx -y6.2 创建Nginx站点配置文件
在/etc/nginx/sites-available/目录下创建站点配置文件:
sudo vim /etc/nginx/sites-available/myproject配置文件内容如下:
server {
listen 80;
server_name 你的域名 服务器公网IP;
# 项目根目录
root /var/www/myproject;
# 日志配置
access_log /var/log/nginx/myproject_access.log;
error_log /var/log/nginx/myproject_error.log;
# 静态文件处理
location /static/ {
alias /var/www/myproject/static/;
expires 30d;
}
# 媒体文件处理
location /media/ {
alias /var/www/myproject/media/;
expires 30d;
}
# 动态请求转发给uWSGI
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/myproject/myproject.sock;
uwsgi_read_timeout 300;
uwsgi_connect_timeout 300;
uwsgi_send_timeout 300;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
# 禁止访问敏感文件
location ~ (settings\.py|wsgi\.py) {
deny all;
}
}6.3 启用站点配置
# 创建符号链接启用站点
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/
# 测试Nginx配置语法
sudo nginx -t
# 重新加载Nginx配置
sudo systemctl reload nginx7. Systemd进程守护配置
为了让uWSGI在服务器重启后自动启动,并能够在异常退出时自动恢复,需要配置Systemd服务。
7.1 创建Systemd服务文件
sudo vim /etc/systemd/system/uwsgi.service服务文件内容如下:
[Unit]
Description=uWSGI service for Django project
After=network.target
[Service]
Type=forking
PIDFile=/var/www/myproject/uwsgi.pid
ExecStart=/var/www/myproject/venv/bin/uwsgi --ini /var/www/myproject/uwsgi.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=always
RestartSec=10
User=www-data
Group=www-data
[Install]
WantedBy=multi-user.target7.2 启动并启用uWSGI服务
# 重新加载Systemd配置
sudo systemctl daemon-reload
# 启动uWSGI服务
sudo systemctl start uwsgi
# 设置开机自启
sudo systemctl enable uwsgi
# 查看服务状态
sudo systemctl status uwsgi8. HTTPS证书配置(可选但推荐)
生产环境强烈建议启用HTTPS以保障数据传输安全。使用Let's Encrypt免费SSL证书:
8.1 安装Certbot
sudo apt install certbot python3-certbot-nginx -y8.2 获取并配置SSL证书
# 自动获取证书并配置Nginx
sudo certbot --nginx -d 你的域名
# 按照提示输入邮箱并同意服务条款Certbot会自动修改Nginx配置文件,启用HTTPS并配置证书自动续期。
8.3 配置自动续期
# 测试续期功能
sudo certbot renew --dry-run
# 自动续期任务已由systemd定时器管理,无需额外配置9. 部署验证与测试
9.1 检查所有服务状态
# 检查Nginx状态
sudo systemctl status nginx
# 检查uWSGI状态
sudo systemctl status uwsgi
# 检查端口监听
sudo netstat -tlnp | grep -E '80|443|8001'9.2 测试网站访问
在浏览器中输入服务器公网IP或域名,应该能够正常访问Django网站。如果遇到问题,检查以下日志:
# Nginx错误日志
sudo tail -f /var/log/nginx/myproject_error.log
# uWSGI日志
sudo tail -f /var/www/myproject/uwsgi.log10. 性能优化与调优
10.1 uWSGI性能调优
根据服务器配置和预期并发量调整uWSGI参数:
# 根据CPU核心数调整进程数
processes = 4 # 建议设为CPU核心数
# 根据内存大小调整线程数
threads = 2 # 每个进程的线程数
# 限制最大请求数防止内存泄漏
max-requests = 5000
# 设置请求超时
harakiri = 6010.2 Nginx性能调优
在Nginx配置中添加以下优化参数:
# 工作进程数(通常设为CPU核心数)
worker_processes auto;
# 每个工作进程的最大连接数
worker_connections 1024;
# 启用gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1000;
# 静态资源缓存
location /static/ {
alias /var/www/myproject/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}10.3 数据库连接优化
在Django的settings.py中配置数据库连接池:
# 使用django-db-connection-pool或配置CONN_MAX_AGE
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
'CONN_MAX_AGE': 600, # 连接复用时间(秒)
'OPTIONS': {
'connect_timeout': 10,
}
}
}11. 常见问题排查
11.1 502 Bad Gateway错误
这通常是uWSGI服务未启动或Socket文件权限问题导致的。解决方法:
# 检查uWSGI服务状态
sudo systemctl status uwsgi
# 检查Socket文件是否存在
ls -la /var/www/myproject/myproject.sock
# 检查Nginx用户是否有权限访问Socket文件
sudo chmod 666 /var/www/myproject/myproject.sock11.2 静态文件404错误
静态文件无法访问通常是因为collectstatic未执行或Nginx静态路径配置错误:
# 重新收集静态文件
python manage.py collectstatic --noinput
# 检查静态文件目录是否存在
ls -la /var/www/myproject/static/
# 检查Nginx配置中的静态路径是否正确11.3 权限问题
确保Nginx用户(www-data)对项目目录有读取和执行权限:
sudo chown -R www-data:www-data /var/www/myproject
sudo chmod -R 755 /var/www/myproject12. 总结
本文详细介绍了在华为云ECS上使用Nginx+uWSGI部署Django项目的完整流程。从ECS实例选购、安全组配置、Python环境搭建,到uWSGI和Nginx的配置文件编写、Systemd进程守护、HTTPS证书配置,再到性能优化和常见问题排查,涵盖了生产环境部署的各个环节。这套部署架构是业界公认且经过大规模验证的最佳实践。
通过本文的指导,你应该能够将Django应用从本地开发环境平滑迁移至华为云生产环境。记住,部署不是一次性的工作,而是一个持续优化的过程。定期更新依赖包、监控日志、调整性能参数,才能让网站长期稳定高效地运行。
问答环节
问1:Django自带的runserver为什么不能用于生产环境?
答:runserver是Django内置的开发服务器,仅适用于本地调试。它不具备生产环境所需的并发处理能力、安全防护和稳定性。在生产环境中,必须使用uWSGI、Gunicorn等专业应用服务器配合Nginx等Web服务器构建分层架构。
问2:uWSGI配置文件中的socket和http有什么区别?
答:socket参数用于配置uWSGI与Nginx之间的通信方式(Unix Socket或TCP Socket),用于内部进程间通信;http参数则是让uWSGI直接以HTTP服务方式监听端口,供外部直接访问。在生产环境中,推荐使用socket方式让Nginx作为前端反向代理。
问3:为什么要使用虚拟环境部署Django项目?
答:虚拟环境可以将项目依赖与系统Python环境隔离,避免不同项目之间的包版本冲突。同时,虚拟环境使得项目依赖管理更加清晰,便于迁移和回滚。
问4:collectstatic命令的作用是什么?
答:collectstatic命令将Django项目中所有应用(包括第三方应用)的静态文件收集到STATIC_ROOT指定的统一目录中。在生产环境中,由Nginx直接提供这些静态文件的访问服务,而不再由Django处理,从而大幅提升静态资源的加载速度。
问5:如何让uWSGI在服务器重启后自动启动?
答:通过配置Systemd服务来实现进程守护。创建/etc/systemd/system/uwsgi.service文件,配置ExecStart、Restart等参数,然后执行systemctl enable uwsgi即可实现开机自启。
问6:部署后出现502 Bad Gateway错误该如何排查?
答:502错误通常表示Nginx无法连接到uWSGI服务。排查步骤:首先检查uWSGI服务是否正常运行(systemctl status uwsgi);其次检查Socket文件是否存在以及权限是否正确;最后查看uWSGI和Nginx的错误日志获取详细错误信息。




