
1. 项目概述为什么一个Python Web应用非得绕过开发服务器直面uWSGI Nginx你写完一个Django或Flask应用python manage.py runserver或flask run一敲本地浏览器里页面唰一下就出来了——这感觉太爽了。但只要项目要上线、哪怕只是给同事演示个内部系统这个命令立刻从“救星”变成“定时炸弹”。它不是设计来扛真实流量的单线程、无超时控制、不处理静态文件、不防DDoS、连基本的请求队列都靠Python解释器硬撑。我见过太多团队在测试环境用runserver跑得好好的一上预发环境3个并发请求就让整个服务卡死日志里全是OSError: [Errno 24] Too many open files。这不是代码问题是架构选型没跨过那道坎。uWSGI Nginx这套组合就是Python Web生产环境的“标准答案”。它不是某个厂商的私有方案而是经过十年以上千万级站点验证的工业级流水线uWSGI负责把Python代码编译成可被Web服务器理解的字节码管理进程生命周期、内存回收、热重载Nginx则像一个经验老到的交通警察负责接收所有HTTP请求、分发给后端uWSGI进程、缓存静态资源、抵御慢速攻击、做SSL终止、甚至能根据URL路径把API请求和前端资源请求分流到不同后端。它们之间通过Unix Socket或TCP协议通信数据不经过磁盘全程在内存中流转吞吐量比单线程开发服务器高出两个数量级。关键词里反复出现的“windows 安装uwsgi”、“nginx配置”、“centos7 nginx uwsgi django drf vite vue docker mysql redis生产环境”恰恰说明这不是一个孤立的技术点而是一整套基础设施能力。你在Windows上装uWSGI本质上是在模拟Linux生产环境的最小闭环你调nginx.conf里的client_max_body_size解决的是前端上传大文件报413错误的现实痛点你研究if using custom web server, verify that web server is sending .br files with背后是现代Web对Brotli压缩的强制要求——这些都不是教科书里的理论是每天在服务器日志里跳出来的血淋淋的告警。这篇文章不讲“什么是WSGI”而是直接带你把一台空服务器变成能扛住真实业务流量的Python Web工厂。无论你是刚学完print(Hello World)的零基础新手还是正在为线上500错误焦头烂额的运维老手接下来的内容每一步都能复制粘贴执行每一个参数都有它的脾气和来历。2. 核心技术栈拆解WSGI、uWSGI、Nginx三者如何各司其职又无缝咬合2.1 WSGIPython Web世界的“普通话”不是软件是契约很多人第一次看到“WSGI”就以为是个要下载安装的程序其实它连一行代码都不是。WSGIWeb Server Gateway Interface是Python社区在2003年定下的一个接口规范就像USB接口标准——它不规定U盘长什么样只规定U盘插进电脑时必须用哪几根针脚传输数据、电压多少、握手信号怎么发。对Python Web而言WSGI规范强制约定了两件事Web服务器如Nginx必须提供一个可调用对象callable这个对象接收两个参数environ一个包含所有HTTP请求头、方法、路径、客户端IP等信息的字典和start_response一个回调函数用于设置HTTP状态码和响应头Python应用如Django的wsgi.py必须返回一个可迭代对象通常是列表或生成器里面是HTTP响应体的字节流。提示你可以把WSGI想象成餐厅里的“传菜口”。厨房Python应用把做好的菜响应体打包好放在传菜口WSGI callable服务员Web服务器从传菜口取走菜品加上菜单状态码、Content-Type头端给客人浏览器。厨房和餐厅不用知道对方怎么运作只要遵守传菜口的尺寸和流程就行。Django、Flask、FastAPI等框架都内置了符合WSGI规范的入口模块。比如Django项目根目录下的wsgi.py文件核心就这一行application get_wsgi_application()这个application变量就是WSGI规范要求的那个“可调用对象”。它不是你写的业务逻辑而是框架为你准备好的、严格遵循WSGI契约的“翻译官”。2.2 uWSGIPython应用的“职业经理人”专治各种不服如果WSGI是契约uWSGI就是那个拿着契约去监督执行、管理团队、应对突发状况的职业经理人。它是一个独立的、用C语言编写的应用服务器Application Server核心使命是把Python应用的WSGI接口包装成Web服务器如Nginx能高效、安全、稳定调用的服务。它干的活远超“翻译”进程/线程管理runserver是单进程单线程uWSGI可以开4个master进程每个下面管8个worker子进程每个worker还能开4个线程——总共128个并发处理单元且能根据CPU负载自动伸缩。内存与资源隔离一个worker进程崩溃其他worker照常工作不会导致整个应用雪崩。它还内置了max-requests1000参数强制worker处理1000个请求后自动重启防止内存泄漏累积。优雅重启与热重载uwsgi --reload myapp.pid命令能让uWSGI在不中断服务的情况下平滑加载新代码用户完全感知不到。协议桥接它原生支持HTTP、FastCGI、SCGI但最常用的是与Nginx通信的uwsgi协议——一种比HTTP更轻量、专为进程间通信优化的二进制协议。注意uWSGI不是Web服务器它不直接监听80端口也不处理SSL证书。它的定位非常清晰只专注运行Python代码把网络层的事彻底交给更专业的Nginx。这就是“专业分工”的威力。2.3 NginxWeb流量的“中央调度室”稳、快、狠Nginx发音同“engine X”是一个高性能的HTTP服务器和反向代理服务器。它和Apache最大的区别在于架构Apache为每个连接创建一个进程或线程阻塞式而Nginx用一个主线程少量工作线程event-driven通过异步非阻塞I/O模型轻松支撑数万并发连接。在uWSGINginx架构中Nginx扮演三个关键角色反向代理Reverse Proxy这是它最核心的身份。外部用户访问https://myapp.comDNS解析到Nginx服务器IPNginx收到请求后不自己处理而是根据配置如location / { proxy_pass http://127.0.0.1:8001; }把请求转发给本机的uWSGI进程通常监听在127.0.0.1:8001或/tmp/uwsgi.sock。用户只和Nginx打交道完全不知道后端是Python、Java还是Node.js。静态文件服务器Static File ServerHTML、CSS、JS、图片等文件根本不需要Python应用处理。Nginx直接从磁盘读取并返回速度比Python应用快10倍以上。配置一行location /static { alias /var/www/myapp/static/; }即可。安全网关Security Gateway它能做速率限制limit_req、IP黑名单deny 192.168.1.100;、请求体大小限制client_max_body_size 10M;解决413错误、SSL/TLS终止卸载HTTPS加密把解密后的HTTP请求发给uWSGI、甚至WAFWeb应用防火墙基础规则。三者关系用一张表厘清组件类型主要职责是否直接面向用户典型监听地址WSGI规范Interface定义Python应用与Web服务器间的通信契约否抽象层无uWSGI应用服务器App Server运行Python代码、管理进程、处理业务逻辑否仅接受Nginx转发127.0.0.1:8001或/tmp/uwsgi.sockNginxWeb服务器/反向代理Web Server接收用户请求、分发给uWSGI、托管静态文件、保障安全是用户唯一入口0.0.0.0:80/0.0.0.0:443这个分工让每个组件都做到了极致Nginx处理海量连接和网络IOuWSGI专注Python执行效率WSGI规范确保生态兼容性。任何试图让Python应用自己监听80端口、处理SSL、抗DDoS的做法都是在重复造轮子而且造得比Nginx差得多。3. 实操部署全流程从零开始在CentOS 7上搭建DjangouWSGINginx生产环境3.1 环境准备干净的CentOS 7系统与基础依赖我们以最典型的生产环境——CentOS 7内核3.10Python 2.7默认为蓝本。虽然现在推荐用Ubuntu 22.04或CentOS Stream但大量企业服务器仍在用CentOS 7它的稳定性是经过时间检验的。切记不要在你的开发机或Mac上跟着操作一定要在一台全新的、最小化安装的CentOS 7虚拟机或云服务器上进行。我用的是阿里云ECS配置2核4G系统盘40GB。第一步更新系统并安装基础工具# 切换到root用户后续所有命令均以此身份执行 sudo su - # 更新系统包耗时约5-10分钟 yum update -y # 安装常用工具wget下载、vim编辑器、gcc编译uWSGI必需、openssl-develSSL支持 yum install -y wget vim-enhanced gcc openssl-devel # 安装Python 3.8CentOS 7默认只有Python 2.7必须升级 # 先安装编译依赖 yum groupinstall -y Development Tools yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel expat-devel # 下载Python 3.8.18源码选择这个版本是因为它对CentOS 7兼容性最好 cd /usr/src wget https://www.python.org/ftp/python/3.8.18/Python-3.8.18.tgz tar xzf Python-3.8.18.tgz cd Python-3.8.18 # 编译安装--enable-optimizations开启PGO优化提升性能约10% ./configure --enable-optimizations make -j$(nproc) # -j参数让make使用所有CPU核心并行编译大幅缩短时间 make altinstall # 使用altinstall避免覆盖系统默认的python2.7 # 验证安装 python3.8 --version # 应输出 Python 3.8.18实操心得make -j$(nproc)是提速关键。我在2核机器上实测不加-j编译要22分钟加了只要7分钟。make altinstall是安全红线——它安装的可执行文件叫python3.8而不是python3这样就不会破坏系统依赖python3的其他软件如yum。很多新手在这里翻车把系统搞瘫痪。3.2 创建项目与Python虚拟环境隔离是生产环境的生命线永远不要在系统Python环境中直接pip install这是所有线上事故的起点。我们必须为每个项目创建独立的、纯净的Python环境。# 创建项目目录结构遵循Linux最佳实践 mkdir -p /var/www/mydjangoapp/{src,logs,static,media} chown -R $USER:$USER /var/www/mydjangoapp chmod -R 755 /var/www/mydjangoapp # 进入项目源码目录 cd /var/www/mydjangoapp/src # 创建并激活Python 3.8虚拟环境 python3.8 -m venv venv source venv/bin/activate # 升级pip到最新版旧版pip在安装uWSGI时会报错 pip install --upgrade pip # 安装Django这里用3.2.25 LTS版本长期支持企业首选 pip install Django3.2.25 # 创建Django项目注意--name参数指定项目名-p指定路径 django-admin startproject mysite . # 修改Django配置适配生产环境 vim mysite/settings.py在settings.py中找到并修改以下关键配置这是生产环境的铁律# SECURITY WARNING: keep the secret key used in production secret! # 生产环境绝不能用默认的SECRET_KEY用下面命令生成一个强随机密钥 # python3.8 -c from django.core.management.utils import get_random_secret_key; print(get_random_secret_key()) SECRET_KEY your_very_strong_random_secret_key_here # SECURITY WARNING: dont run with debug turned on in production! DEBUG False # 必须为False否则会暴露敏感信息 # 允许访问的域名白名单防止HTTP Host头攻击 ALLOWED_HOSTS [myapp.com, www.myapp.com, 123.45.67.89] # 替换为你的域名或IP # 静态文件配置Django收集到的CSS/JS等 STATIC_URL /static/ STATIC_ROOT /var/www/mydjangoapp/static/ # 注意这是Nginx将要服务的绝对路径 # 媒体文件配置用户上传的图片等 MEDIA_URL /media/ MEDIA_ROOT /var/www/mydjangoapp/media/ # 数据库配置这里用SQLite做演示生产环境务必换成PostgreSQL或MySQL DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: /var/www/mydjangoapp/db.sqlite3, } } # 日志配置非常重要没有日志线上问题等于瞎子 LOGGING { version: 1, disable_existing_loggers: False, formatters: { verbose: { format: {levelname} {asctime} {module} {process:d} {thread:d} {message}, style: {, }, }, handlers: { file: { level: INFO, class: logging.handlers.RotatingFileHandler, filename: /var/www/mydjangoapp/logs/django.log, maxBytes: 1024*1024*5, # 5MB backupCount: 5, formatter: verbose, }, }, root: { handlers: [file], level: INFO, }, }注意ALLOWED_HOSTS是安全开关。如果你填[*]Django会拒绝所有请求并返回400 Bad Request。必须精确列出你的域名或IP。DEBUGFalse后Django的错误页面会消失所有错误都会写入日志所以LOGGING配置必须到位。3.3 安装与配置uWSGI让Django应用“活”起来uWSGI是整个链条的发动机它的配置文件决定了应用的生死。# 在已激活的虚拟环境中安装uWSGI pip install uwsgi # 创建uWSGI配置文件纯文本无后缀 vim /var/www/mydjangoapp/uwsgi.iniuwsgi.ini内容如下每一行都有深意# uWSGI配置文件/var/www/mydjangoapp/uwsgi.ini # 项目基础信息 [uwsgi] project mydjangoapp uid root gid root base /var/www # Python相关 home %(base)/%(project)/src/venv # 虚拟环境路径 pythonpath %(base)/%(project)/src # Python模块搜索路径 module mysite.wsgi:application # WSGI入口格式模块名:可调用对象名 # 进程与性能 master true # 开启master进程管理worker processes 4 # 启动4个worker进程根据CPU核心数调整2核建议2-4个 threads 2 # 每个worker开2个线程适合I/O密集型Django max-requests 1000 # 每个worker处理1000个请求后自动重启防内存泄漏 vacuum true # worker退出时自动清理内存和文件描述符 # 通信方式关键选择Unix Socket比TCP更高效、更安全 socket /var/www/%(project)/%(project).sock chmod-socket 664 # 设置socket文件权限让Nginx能读写 chown-socket root:nginx # socket文件属主为root属组为nginx uid root gid nginx # 安全与日志 die-on-term true # 收到TERM信号时优雅退出 logto /var/www/%(project)/logs/uwsgi.log # uWSGI自己的日志 log-maxsize 10000000 # 10MB log-backupname /var/www/%(project)/logs/uwsgi.log.old解析socket /var/www/%(project)/%(project).sock这行是精髓。它让uWSGI创建一个Unix域套接字文件.sock而不是监听TCP端口。Unix Socket是同一台机器上进程间通信的最快方式没有网络协议栈开销且天然隔离——只有本机进程能访问这个文件。chown-socket root:nginx确保Nginx的worker进程通常以nginx用户运行能通过这个文件与uWSGI通信。chmod-socket 664赋予属主和属组读写权限其他用户只有读权限安全又实用。启动uWSGI进行测试# 启动uWSGI后台运行-d参数指定日志文件 uwsgi --ini /var/www/mydjangoapp/uwsgi.ini -d /var/www/mydjangoapp/logs/uwsgi.log # 查看uWSGI是否启动成功 ps aux | grep uwsgi # 应该看到master进程和4个worker进程 # 查看uWSGI日志 tail -f /var/www/mydjangoapp/logs/uwsgi.log # 如果看到WSGI app 0 (mountpoint) ready in X seconds说明Django应用已加载成功此时uWSGI已经在后台运行但它监听的是.sock文件你无法用浏览器直接访问。下一步让Nginx来“代言”。3.4 安装与配置Nginx架起用户与uWSGI之间的桥梁# 添加Nginx官方仓库确保安装最新稳定版 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm # 安装Nginx yum install -y nginx # 启动Nginx并设置开机自启 systemctl start nginx systemctl enable nginx # 检查Nginx状态 systemctl status nginx # 应显示active (running)Nginx的核心配置在/etc/nginx/nginx.conf但我们不直接修改它而是为每个站点创建独立的配置文件便于管理# 删除默认的default.conf创建我们的站点配置 rm -f /etc/nginx/conf.d/default.conf vim /etc/nginx/conf.d/mydjangoapp.confmydjangoapp.conf内容如下这是生产环境的黄金配置# Nginx配置文件/etc/nginx/conf.d/mydjangoapp.conf upstream django_app { # 指向uWSGI的Unix Socket server unix:/var/www/mydjangoapp/mydjangoapp.sock; } server { listen 80; server_name myapp.com www.myapp.com; # 替换为你的域名 charset utf-8; # 最大请求体大小解决413错误前端上传大文件 client_max_body_size 10M; # 访问日志按天轮转 access_log /var/www/mydjangoapp/logs/nginx_access.log main; error_log /var/www/mydjangoapp/logs/nginx_error.log warn; # 处理静态文件CSS, JS, 图片 location /static { alias /var/www/mydjangoapp/static/; expires 1h; # 浏览器缓存1小时 add_header Cache-Control public, immutable; } # 处理媒体文件用户上传 location /media { alias /var/www/mydjangoapp/media/; expires 1d; } # 将所有其他请求转发给Django应用 location / { # 关键将请求转发给upstream定义的django_app proxy_pass http://django_app; # 传递关键HTTP头让Django知道真实情况 proxy_set_header Host $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; # 超时设置防止uWSGI慢请求拖垮Nginx proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; # 重要启用uWSGI协议不是HTTP include /etc/nginx/uwsgi_params; } }解析upstream django_app定义了一个后端服务器组里面只有一个成员unix:/var/www/mydjangoapp/mydjangoapp.sock。location /块中的proxy_pass http://django_app;看似是HTTP但因为include /etc/nginx/uwsgi_params;的存在Nginx会自动将这个proxy_pass转换为uwsgi协议通信。uwsgi_params是Nginx自带的文件里面包含了所有uWSGI需要的环境变量映射比如UWSGI_SCRIPT、UWSGI_CHDIR等。proxy_set_header系列指令至关重要它们把原始请求的真实信息如用户IP、协议类型告诉Django否则Django拿到的全是127.0.0.1无法做IP限流或HTTPS判断。最后一步收集Django静态文件并重启服务# 激活虚拟环境 source /var/www/mydjangoapp/src/venv/bin/activate # 进入项目目录 cd /var/www/mydjangoapp/src # 收集所有静态文件到STATIC_ROOT指定的目录 python3.8 manage.py collectstatic --noinput # 重启Nginx重新加载配置 systemctl restart nginx # 重启uWSGI先杀掉再启动确保配置生效 pkill -f uwsgi --ini /var/www/mydjangoapp/uwsgi.ini uwsgi --ini /var/www/mydjangoapp/uwsgi.ini -d /var/www/mydjangoapp/logs/uwsgi.log现在打开你的浏览器访问http://你的服务器IP或http://你的域名。如果一切顺利你应该看到Django的欢迎页面这意味着整个uWSGINginx流水线已经打通。4. 常见问题与排查技巧实录那些让你抓狂的413、502、504错误4.1 HTTP 413 Request Entity Too Large上传文件失败的元凶现象前端用input typefile上传一个15MB的视频点击提交后浏览器Network面板显示状态码413Nginx日志里有client intended to send too large body。原因Nginx默认client_max_body_size是1MB超过即拒收。这是一个安全保护但太小了。排查步骤检查Nginx配置grep client_max_body_size /etc/nginx/conf.d/mydjangoapp.conf确认值是否足够如10M。检查Nginx是否重载systemctl reload nginx不是restartreload只重载配置不中断服务。检查uWSGI是否有额外限制uWSGI默认不限制请求体大小但可以在uwsgi.ini中加buffer-size 3276832KB来增加缓冲区不过通常Nginx层限制就够了。终极解决方案在mydjangoapp.conf的server块中明确设置client_max_body_size 100M; # 根据业务需求调整100MB足够大然后systemctl reload nginx。注意这个值不能设得无限大否则可能被恶意用户用超大请求耗尽服务器内存。4.2 HTTP 502 Bad GatewayNginx找不到uWSGI现象浏览器显示502Nginx错误日志/var/www/mydjangoapp/logs/nginx_error.log里有connect() to unix:/var/www/mydjangoapp/mydjangoapp.sock failed (111: Connection refused)。原因Nginx尝试连接uWSGI的socket文件但文件不存在、权限不对、或uWSGI根本没在运行。排查四步法检查uWSGI进程ps aux | grep uwsgi。如果没有输出说明uWSGI没启动。执行uwsgi --ini /var/www/mydjangoapp/uwsgi.ini看终端报错。检查socket文件ls -l /var/www/mydjangoapp/mydjangoapp.sock。如果文件不存在说明uWSGI启动失败如果存在看权限是否为srw-rw-r--属主root属组nginx。如果不是手动修复chown root:nginx /var/www/mydjangoapp/mydjangoapp.sock chmod 664 /var/www/mydjangoapp/mydjangoapp.sock。检查uWSGI日志tail -f /var/www/mydjangoapp/logs/uwsgi.log。最常见的错误是Python路径错误ImportError: No module named mysite这通常是因为pythonpath或module配置错了。仔细核对uwsgi.ini里的pythonpath是否指向/var/www/mydjangoapp/srcmodule是否是mysite.wsgi:application。检查SELinuxCentOS特有CentOS 7默认开启SELinux它可能阻止Nginx访问socket文件。临时关闭测试setenforce 0。如果关闭后502消失说明是SELinux问题。永久解决方案是设置正确策略setsebool -P httpd_can_network_connect 1。实操心得我踩过最深的坑是module配置。Django项目结构是/src/mysite/mysite/wsgi.py有人会误写成src.mysite.wsgi:application。正确的module是mysite.wsgi:application因为pythonpath已经把/src加进了Python路径mysite就是顶层包名。4.3 HTTP 504 Gateway TimeoutuWSGI处理太慢Nginx等不及了现象浏览器显示504Nginx错误日志有upstream timed out (110: Connection timed out) while reading response header from upstream。原因Nginx向uWSGI发起请求后在proxy_read_timeout设定的时间内默认60秒没有收到uWSGI的完整响应头于是Nginx主动断开连接返回504。排查与优化首先确认是真慢还是假慢在uWSGI日志里搜索OOPS或Segmentation fault看是否有worker崩溃。如果有加大processes或threads或检查代码是否有死循环。检查数据库查询一个未加索引的SELECT * FROM huge_table WHERE name LIKE %xxx%可能执行30秒。用Django Debug Toolbar或数据库慢查询日志定位。调整超时时间在mydjangoapp.conf中适当延长超时proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 120s; # 关键从默认60秒延长到120秒终极方案异步任务对于必须耗时的操作如发送邮件、生成报表不要在HTTP请求里同步执行。用CeleryRedis/RabbitMQ把它扔到后台队列HTTP请求立即返回“任务已提交”前端用AJAX轮询结果。4.4 uWSGI启动失败ImportError、ModuleNotFoundError的迷宫现象执行uwsgi --ini ...后终端直接报错退出日志里是ImportError: No module named django或ModuleNotFoundError: No module named mysite。原因uWSGI找不到Python模块。根源几乎总是home虚拟环境路径或pythonpath代码路径配置错误。快速诊断表错误信息最可能原因检查命令修复方案No module named djangohome路径错误uWSGI没激活虚拟环境ls /var/www/mydjangoapp/src/venv/bin/activate确认home指向/var/www/mydjangoapp/src/venv且该路径下有bin/activate文件No module named mysitepythonpath错误Python找不到mysite包ls /var/www/mydjangoapp/src/mysite/wsgi.pypythonpath必须是/var/www/mydjangoapp/src且该目录下有mysite文件夹含__init__.pyNo module named mysite.wsgimodule配置错误或wsgi.py文件损坏cat /var/www/mydjangoapp/src/mysite/wsgi.py | head -10module应为mysite.wsgi:application且wsgi.py第一行是import os最后一行是application get_wsgi_application()万能调试命令在uWSGI配置里加py-autoreload1它会让uWSGI在检测到Python文件变化时自动重启方便开发调试。但生产环境严禁使用因为它会频繁fork进程消耗CPU。5. 进阶与生产加固从能跑通到能扛住百万并发5.1 使用Supervisor守护uWSGI进程让它永不宕机uwsgi --ini ...命令启动的进程一旦SSH断开就会退出。生产环境需要一个“看门狗”进程时刻监控uWSGI一旦崩溃就自动拉起。# 安装Supervisor yum install -y epel-release yum install -y supervisor # 创建Supervisor配置文件 vim /etc/supervisord.d/mydjangoapp.ini[program:mydjangoapp] commanduwsgi --ini /var/www/mydjangoapp/uwsgi.ini directory/var/www/mydjangoapp/src userroot autostarttrue autorestarttrue redirect_stderrtrue stdout_logfile/var/www/mydjangoapp/logs/supervisor.log# 启动Supervisor并重载配置 systemctl start supervisord systemctl enable supervisord supervisorctl reread supervisorctl update supervisorctl start mydjangoapp # 查看状态 supervisorctl status现在即使你kill -9掉uWSGI进程Supervisor也会在1秒内把它拉起来。supervisorctl命令还能让你一键重启、查看日志比手动pkill优雅得多。5.2 Nginx SSL/TLS配置让网站拥有绿色小锁没有HTTPS的网站在现代浏览器里会被标记为“不安全”。用Lets Encrypt免费获取SSL证书。# 安装Certbot yum install -y certbot python3-certbot-nginx # 获取证书假设你的域名myapp.com已解析到服务器IP certbot --nginx -d myapp.com -d www.myapp.com # Certbot会自动修改/etc/nginx/conf.d/mydjangoapp.conf添加443端口配置和重定向 # 你只需重启Nginx systemctl restart nginxCertbot生成的证书90天过期它会自动添加一个cron任务来续期。你无需操心。5.3 性能压测与调优用ab命令量化你的服务器能力别猜要测。Apache Bench (ab) 是最简单的HTTP压测工具。# 安装 yum install -y httpd-tools # 对首页进行100并发、1000次请求的压测 ab -n 1000 -c 100 http://123.45.67.89/ # 关键指标解读 # Requests per second: 324.56 [#/sec] (mean) # 每秒处理324个请求 # Time per request: 308.119 [ms] (mean) # 每个请求平均耗时308ms # Percentage of the requests served within