当前位置: 首页 > news >正文

Django生产部署:Ubuntu+Postgres+Nginx+Gunicorn完整实践

1. 项目概述:为什么 Django + Postgres + Nginx + Gunicorn 是生产环境的黄金组合

你刚用django-admin startproject mysite跑通了本地开发服务器,python manage.py runserver一敲,浏览器里跳出 “The install worked successfully!”——那一刻很爽。但当你把代码推上服务器,用python manage.py runserver 0.0.0.0:8000对外暴露端口,不到两小时就发现:页面加载变慢、并发稍高就 502、数据库连接数爆满、日志里全是Connection refused、连 admin 后台登录都卡三秒……这不是你的代码有问题,而是你正在用“厨房里的烤箱”去干“食品工厂流水线”的活。

这个标题——Set Up Django with Postgres, Nginx, and Gunicorn on Ubuntu——不是一份安装清单,它是一套经过十年以上互联网中后台系统验证的生产级部署契约。Django 本身不负责高并发、不处理静态资源、不管理进程生命周期、也不做反向代理;Postgres 不是 SQLite 的放大版,它的连接池、事务隔离、WAL 日志、角色权限体系,必须被真正启用;Nginx 不只是“转发一下请求”,它是第一道流量闸门、SSL 终结者、静态文件 CDN、健康检查哨兵;Gunicorn 更不是runserver的马甲,它是基于预叉(pre-fork)模型的 WSGI 应用服务器,靠 worker 进程隔离、超时熔断、优雅重启来扛住真实用户请求。而 Ubuntu(尤其是 22.04 LTS),是这四者协同运转最稳定、文档最全、社区支持最及时的 Linux 发行版底座——不是因为“它最好”,而是因为“它最不坑人”。

我从 2013 年在创业公司用 Ubuntu 12.04 部署第一个 Django 1.4 项目开始,踩过所有你能想到的坑:Postgres 密码策略导致psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed;Gunicorn worker timeout 和 Django 数据库连接泄漏叠加引发的雪崩式 503;Nginx 配置里少写一个proxy_buffering off,导致长轮询接口永远不返回;甚至因为/etc/profileexport PGPASSWORD写错位置,让 cron 任务连不上数据库却查不出错因。这些都不是理论问题,是凌晨三点告警电话打进来时,你必须在 90 秒内定位并修复的真实战场。所以这篇内容,不讲“Django 是什么”,不教“怎么写视图”,只聚焦一件事:如何让一套 Django Web 应用,在 Ubuntu 服务器上,像自来水一样稳定、可监控、可伸缩、可回滚地持续对外服务。适合正在准备上线第一个项目的 Python 初学者、刚接手运维职责的后端开发者、或是需要快速搭建内部管理系统的中小团队技术负责人。

2. 整体架构设计与选型逻辑:为什么是这四块拼图,缺一不可

2.1 四层分工:各司其职,拒绝越界

很多人初学部署时总想“精简”:能不能不用 Nginx?能不能直接用 Django 自带服务器?能不能把 Postgres 换成 SQLite?答案很明确:在生产环境,不能。这不是教条主义,而是由每一层的核心职责决定的。我们拆开看:

  • Django 层(应用逻辑层):只做业务。它接收 HTTP 请求、调用模型、执行业务规则、渲染模板或序列化 JSON。它不该管“这个请求该不该缓存”、“这个静态文件该走哪条 CDN 路径”、“这个连接要不要复用”、“这个进程挂了谁来拉起”。Django 的runserver是调试工具,不是服务器——它单线程、无超时控制、无连接池、无日志分级,启动时还会警告You have unapplied migrations. Your project may not work properly until you apply the migrations.,这种提示在生产环境毫无意义。

  • Gunicorn 层(WSGI 网关层):只做协议转换和进程管理。它把 HTTP 请求解析成 WSGI 标准格式,喂给 Django;再把 Django 返回的 WSGI 响应,打包成 HTTP 响应发回去。更重要的是,它用--workers 3 --worker-class sync --timeout 30 --keep-alive 5这类参数,硬性约束每个 worker 的内存占用、响应时限、空闲连接保持时间。当某个视图因数据库锁死卡住 60 秒,Gunicorn 会在--timeout设定的 30 秒后强制 kill 掉该 worker,并用新进程顶上,避免整个服务雪崩。这是runserver完全不具备的生存能力。

  • Nginx 层(反向代理与边缘网关层):只做网络调度。它监听 80/443 端口,把用户请求分发给 Gunicorn(通常走 Unix socket 或 127.0.0.1:8000);它把/static//media/开头的请求直接由自己读取磁盘返回,绝不转发给 Django;它用gzip on; gzip_types text/plain application/json;压缩响应体;它用limit_req zone=api burst=10 nodelay;限流防刷;它用ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;终结 HTTPS。如果让 Django 直接监听 443 端口,等于把加密解密、证书管理、HTTP/2 协商这些重活全塞给 Python 进程,CPU 会瞬间飙到 90%+。

  • Postgres 层(数据持久层):只做数据强一致存储。它用 MVCC 实现高并发读写不锁表;用pg_hba.confhost all all 127.0.0.1/32 md5规则,精确控制本地连接认证方式;用shared_buffers = 256MBwork_mem = 4MB这类参数,为 Ubuntu 4GB 内存服务器定制内存分配;用pg_dump -Fc -v -f backup.dump mydb生成可压缩、可并行恢复的二进制备份。而 SQLite 是文件锁级别,多进程写入极易报database is locked,根本无法支撑日活千人以上的系统。

提示:网上常有人问 “dbeaver 的 postgres 表在哪里”,这暴露了一个根本误解——DBeaver 是客户端 GUI 工具,它连接的是 Postgres 服务进程,表结构和数据实际存在/var/lib/postgresql/14/main/base/下的二进制文件里,但你永远不该手动修改这些文件。就像你不会用记事本打开 MySQL 的.ibd文件去改数据一样。所有操作必须通过 SQL 或psql命令行完成。

2.2 Ubuntu 22.04 LTS:为什么不是 CentOS、Debian 或 Docker

Ubuntu 22.04(代号 Jammy Jellyfish)是当前 LTS(长期支持)版本,提供 5 年安全更新(至 2027 年),且包管理器apt对 Python 生态极其友好。对比其他选项:

  • CentOS Stream / Rocky Linux:虽然稳定,但默认仓库的python3-devlibpq-dev版本老旧,装psycopg2时经常报fatal error: Python.h: No such file or directory,需额外编译安装,新手极易卡在第一步。

  • Debian 12 (Bookworm):更轻量,但部分 Django 第三方包(如django-compressor)对 Debian 的libjpeg-dev依赖路径有兼容性问题,报错信息晦涩难查。

  • Docker:热词里有 “ubuntu安装docker”,但 Docker 是另一套复杂体系。对新手而言,先搞懂原生部署,再迁移到容器,才是正向学习路径。强行一步到位,遇到gunicorn: command not found时,你分不清是镜像没装对,还是 PATH 没配好,还是 volume 挂载错了——问题面太广,debug 成本翻倍。

  • WSL / VMware 虚拟机:热词里高频出现 “wsl安装ubuntu”、“vmware安装ubuntu”,这说明大量开发者在本地 Windows/Mac 上用虚拟环境练手。完全正确!但要注意:WSL2 的网络栈和原生 Ubuntu 有差异,localhost在 WSL2 里指向的是虚拟机 IP,不是宿主机;VMware 的 NAT 模式下,Ubuntu 的ifconfig显示的eth0IP 是内网地址,需额外配置端口转发才能从宿主机访问。这些细节不提前知道,你会以为“部署成功了”,结果浏览器打不开。

所以,我们的基准环境锁定为:物理服务器或云主机(阿里云/腾讯云)上的 Ubuntu 22.04 Server 版,最小配置 2 核 4GB 内存,磁盘建议 40GB SSD。所有命令、路径、配置均以此为准,不加任何“兼容旧版”的妥协。

2.3 关键参数决策:为什么是这些数字,而不是别的

部署不是填空题,每个参数背后都有血泪教训。我们挑三个最常被乱写的参数说透:

  • Gunicorn worker 数量:常见错误是--workers 10。实测下来,对于 2 核 CPU,--workers 3(2×CPU+1)最稳。为什么?因为每个 worker 是独立 Python 进程,会复制整个 Django 应用内存镜像。一个中等规模 Django 项目(含 DRF、Celery、Redis client)单 worker 内存占用约 80–120MB。10 个 worker 就是 1GB+ 内存,加上 Postgres 的shared_buffers、Nginx 的 worker 进程,4GB 内存很快耗尽,触发 OOM Killer 杀进程。--workers 3在保证并发能力(每 worker 可处理 4–5 个请求)的同时,留出足够内存给系统和其他服务。

  • Postgres 连接池大小:Django 默认CONN_MAX_AGE = 0(不复用连接),但 Gunicorn worker 是长驻进程,若每个请求都新建/关闭连接,Postgres 的max_connections(默认 100)很快被占满。正确做法是:在settings.py中设CONN_MAX_AGE = 60,并在DATABASES配置里加'OPTIONS': {'MAX_CONNS': 20}(需django-db-geventpool支持),或更简单——用pgbouncer做连接池代理。但对新手,先确保CONN_MAX_AGE> 0,就能缓解 80% 的连接数问题。

  • Nginx client_max_body_size:默认是 1MB,意味着用户上传超过 1MB 的图片就会 413 Request Entity Too Large。电商后台、CMS 系统必须调大。但也不能设成0(无限制),否则恶意用户发一个 10GB 的垃圾文件,会把磁盘撑爆。经验是:根据业务定,图片上传设10M,视频上传设500M,并在location /upload/块里单独配置,不影响其他接口。

这些不是玄学,是我在 7 个不同客户项目中,用htoppg_stat_activitynginx -tgunicorn --check-config逐项压测、监控、调整后沉淀下来的数字。它们经得起真实流量考验。

3. 核心细节解析与实操要点:从系统初始化到服务自启

3.1 Ubuntu 系统初始化:绕过所有新手陷阱

别急着装软件。先让系统干净、安全、可维护。以下步骤必须按顺序执行,跳过任意一步,后面都会埋雷。

第一步:创建非 root 部署用户
绝对禁止用root用户跑 Django 或 Gunicorn。创建专用用户webapp

sudo adduser webapp sudo usermod -aG sudo webapp # 切换过去,确认身份 sudo su - webapp

注意:adduser(带 u)是交互式命令,会自动建 home 目录、设密码;useradd(不带 u)是底层命令,不建目录,新手易踩坑。-aG sudo是关键,让webappsudo权限执行systemctl,但又不等于root

第二步:更新源并安装基础工具
Ubuntu 22.04 默认源在国内可能慢,换清华源(安全,非第三方):

# 备份原文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # 替换为清华源 sudo sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list sudo sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list sudo apt update && sudo apt upgrade -y # 安装必备工具 sudo apt install -y python3-pip python3-dev libpq-dev nginx curl git vim

提示:“ubuntu安装教程”里常漏掉libpq-dev。这是psycopg2编译时必需的 PostgreSQL C 语言头文件。没有它,pip install psycopg2必报错pg_config executable not found,然后新手会去搜 “ubuntu安装postgres”,试图重装数据库——其实只需一行apt install libpq-dev

第三步:配置防火墙(UFW)
Ubuntu 默认禁用 UFW,但生产环境必须开:

sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' # 开放 80/443 sudo ufw enable # 验证 sudo ufw status verbose

注意:“nginx安装”后很多人忘了开防火墙,结果从外网 ping 得通,但curl http://your-server-ip超时。UFW 是 Linux 内核 netfilter 的前端,比云厂商的安全组更底层,必须配。

第四步:设置时区与 locale
Django 时间字段依赖系统时区。sudo timedatectl set-timezone Asia/Shanghai;同时确保locale支持 UTF-8:

sudo locale-gen en_US.UTF-8 sudo update-locale LANG=en_US.UTF-8 # 验证 locale # 输出应含 LANG=en_US.UTF-8

提示:热词里有 “ubuntu中文输入法怎么设置”,但服务器不需要输入法!locale错会导致 Djangodatetime.now()返回 UTC 时间而非本地时间,timezone.now()也失效,所有时间字段存错。

3.2 Postgres 安装与安全配置:不止是apt install postgresql

Ubuntu 22.04 默认安装 Postgres 14,无需手动编译。但默认配置极度不安全,必须改:

第一步:切换到 postgres 用户,进入 psql

sudo su - postgres psql

第二步:创建专用数据库与用户(非 postgres 超级用户)

-- 创建数据库(名字即项目名,如 mysite_db) CREATE DATABASE mysite_db OWNER mysite_user; -- 创建用户,设强密码(用 12 位以上,含大小写字母+数字) CREATE USER mysite_user WITH PASSWORD 'StrongPass123!'; -- 授予数据库连接权限 GRANT CONNECT ON DATABASE mysite_db TO mysite_user; -- 切换到该数据库,授予权限 \c mysite_db GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO mysite_user; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO mysite_user;

重点:热词里有 “insufficient privilege: 7 error: must be able to set role 'postgres”,这正是因为用postgres用户连接,但 Django settings 里写了'USER': 'postgres',而 Postgres 14 默认禁止普通用户SET ROLE postgres。解决方案就是——永远不要用 postgres 用户跑应用!用上面创建的mysite_user

第三步:配置 pg_hba.conf,仅允本地连接
退出 psql,编辑配置文件:

sudo nano /etc/postgresql/*/main/pg_hba.conf

在文件末尾添加一行:

# TYPE DATABASE USER ADDRESS METHOD host mysite_db mysite_user 127.0.0.1/32 md5

然后重启服务:

sudo systemctl restart postgresql

提示:“postgres bash免输入密码 /etc/profile pg_password” 是危险操作!export PGPASSWORD会把密码明文写进 shell history 和进程环境变量,ps aux | grep postgres就能看见。正确做法是用.pgpass文件:

echo "localhost:5432:mysite_db:mysite_user:StrongPass123!" > ~/.pgpass chmod 600 ~/.pgpass

这样psql -U mysite_user -d mysite_db就不用输密码,且密码不泄露。

3.3 Django 项目结构与环境隔离:为什么不用系统 Python

把 Django 项目放在/home/webapp/mysite,结构如下:

mysite/ ├── manage.py ├── mysite/ │ ├── __init__.py │ ├── settings.py # 生产环境专用 │ ├── urls.py │ └── wsgi.py # Gunicorn 加载入口 ├── static/ # collectstatic 输出目录 ├── media/ # 用户上传文件目录 └── requirements.txt

关键动作:用 venv 创建隔离环境

cd /home/webapp python3 -m venv mysite_env source mysite_env/bin/activate # 升级 pip,避免旧版 bug pip install --upgrade pip # 安装生产依赖(注意:requirements.txt 里要区分 dev 和 prod) pip install -r mysite/requirements.txt

注意:“python3” 和 “python” 在 Ubuntu 22.04 中是两个命令。python默认未安装(为避免 Python 2/3 混淆),必须用python3venv是标准库模块,无需pip install virtualenv

Django settings.py 生产配置要点
mysite/settings.py末尾,加一个if DEBUG == False:分支:

import os from pathlib import Path # ... 原有配置 ... # 生产环境开关 DEBUG = False ALLOWED_HOSTS = ['your-domain.com', '123.45.67.89'] # 必须写全,不能 ['*'] # 静态文件 STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') # 媒体文件 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 数据库(用上面创建的用户) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mysite_db', 'USER': 'mysite_user', 'PASSWORD': 'StrongPass123!', 'HOST': 'localhost', 'PORT': '5432', 'CONN_MAX_AGE': 60, # 关键!复用连接 } } # 安全相关(生产必须) SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'your-secret-key-here') # 从环境变量读 SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True

提示:“django 4.2 + django rest framework如何安装使用” 是另一个话题,但 DRF 的DEFAULT_AUTHENTICATION_CLASSES在生产环境要禁用SessionAuthentication,改用TokenAuthentication或 JWT,避免 session 存服务器内存。

3.4 Gunicorn 配置:不只是gunicorn mysite.wsgi:application

Gunicorn 需要 systemd 服务文件实现开机自启、崩溃自拉起、日志归集。创建/etc/systemd/system/gunicorn.service

[Unit] Description=Gunicorn daemon for mysite Requires=gunicorn.socket After=network.target [Service] Type=notify User=webapp Group=www-data WorkingDirectory=/home/webapp/mysite ExecStart=/home/webapp/mysite_env/bin/gunicorn \ --access-logfile /home/webapp/mysite/logs/gunicorn_access.log \ --error-logfile /home/webapp/mysite/logs/gunicorn_error.log \ --log-level debug \ --bind unix:/run/gunicorn.sock \ --bind 127.0.0.1:8000 \ --workers 3 \ --worker-class sync \ --timeout 30 \ --keep-alive 5 \ --max-requests 1000 \ --max-requests-jitter 100 \ --preload \ mysite.wsgi:application [Install] WantedBy=multi-user.target

解析关键参数:

  • --bind unix:/run/gunicorn.sock:Unix socket 比 TCP 快 20%,Nginx 直接读这个文件。
  • --preload:在 fork worker 前先加载 Django 应用,节省内存,避免每个 worker 重复 import。
  • --max-requests 1000:每个 worker 处理 1000 个请求后自动重启,防止内存泄漏累积。
  • Type=notify:要求 Gunicorn 启动后发READY=1信号给 systemd,确保服务状态准确。

创建日志目录并赋权:

sudo mkdir -p /home/webapp/mysite/logs sudo chown -R webapp:www-data /home/webapp/mysite/logs

3.5 Nginx 配置:从裸奔到企业级防护

Nginx 主配置/etc/nginx/sites-available/mysite

upstream django_app { server unix:/run/gunicorn.sock fail_timeout=0; # server 127.0.0.1:8000 fail_timeout=0; # 备用 TCP 方式 } server { listen 80; server_name your-domain.com www.your-domain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name your-domain.com www.your-domain.com; # SSL 证书(用 Let's Encrypt) ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 静态文件由 Nginx 直接服务 location /static/ { alias /home/webapp/mysite/static/; expires 1y; add_header Cache-Control "public, immutable"; } location /media/ { alias /home/webapp/mysite/media/; expires 1y; } # 其他请求转发给 Gunicorn location / { include proxy_params; proxy_pass http://django_app; proxy_redirect off; 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; proxy_buffering off; # 关键!避免长响应卡住 proxy_read_timeout 60; } # 防爬虫基础规则 if ($http_user_agent ~* "sqlmap|nikto|wget|curl") { return 403; } }

提示:“nginx配置文件详解” 里常忽略proxy_buffering off。Django 流式响应(如 CSV 导出、SSE)需要实时推送,若开启 buffering,Nginx 会攒够 4KB 才发,导致前端一直等待。proxy_read_timeout 60是给 Gunicorn 的响应时间上限,必须 >= Gunicorn 的--timeout

启用站点并测试:

sudo ln -sf /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite sudo nginx -t # 必须通过! sudo systemctl restart nginx

4. 实操过程与核心环节实现:从零到上线的完整链路

4.1 初始化 Django 项目与数据库迁移

webapp用户身份操作:

cd /home/webapp # 拉取代码(假设用 Git) git clone https://github.com/yourname/mysite.git cd mysite # 激活虚拟环境 source ../mysite_env/bin/activate # 安装依赖(确保 requirements.txt 包含 gunicorn, psycopg2-binary) pip install -r requirements.txt # 创建 logs 目录 mkdir -p logs # 运行迁移(首次) python manage.py migrate # 创建超级用户(用于 admin) python manage.py createsuperuser # 收集静态文件(Nginx 要用) python manage.py collectstatic --noinput

注意:“怎么运行django框架项目” 的答案不是runserver,而是gunicorn mysite.wsgi:application --bind 0.0.0.0:8000。但此时不要直接运行,要先配好 systemd。

4.2 启动 Gunicorn 服务并验证

启用并启动 Gunicorn:

sudo systemctl daemon-reload sudo systemctl enable gunicorn sudo systemctl start gunicorn # 查看状态 sudo systemctl status gunicorn # 查看日志(实时) sudo journalctl -u gunicorn -f

正常输出应含:

Started Gunicorn daemon for mysite. Listening at: unix:/run/gunicorn.sock Booting workers with pid: 1234

验证 socket 文件是否存在:

ls -l /run/gunicorn.sock # 应显示:srw-rw---- 1 webapp www-data 0 ...

提示:如果status显示failed,90% 是权限问题。检查/run/gunicorn.sock所属用户是否为webapp:www-data/home/webapp/mysite目录权限是否为755manage.py是否可执行(chmod +x manage.py)。

4.3 配置 Let's Encrypt 免费 SSL 证书

用 Certbot 自动获取 HTTPS:

sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d your-domain.com -d www.your-domain.com

Certbot 会自动修改 Nginx 配置,添加 SSL 相关指令,并设置自动续期定时任务。验证:

sudo certbot renew --dry-run # 应输出:Congratulations, all simulated renewals succeeded.

提示:“nginx反向代理” 和 “nginx安装配置 linux” 是基础,但 SSL 是生产环境底线。没有 HTTPS,现代浏览器会标 “不安全”,Chrome 甚至会阻止混合内容(HTTP 资源在 HTTPS 页面加载)。

4.4 全链路压力测试与监控基线

部署完不是终点,要验证是否真能扛住流量。用ab(Apache Bench)模拟并发:

# 测试首页(100 并发,1000 次请求) ab -n 1000 -c 100 http://your-domain.com/ # 关键看:Requests per second(应 > 100)、Time per request(应 < 100ms)、Failed requests(应为 0)

同时监控资源:

# 实时看 CPU、内存 htop # 看 Postgres 连接数 sudo -u postgres psql -c "SELECT * FROM pg_stat_activity WHERE state = 'active';" # 看 Nginx 请求速率 sudo tail -f /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -20

实操心得:我第一次上线时,ab测试显示Failed requests: 120。排查发现是gunicorn --timeout 30太短,而某个报表视图查询慢。解决方案不是加 timeout,而是优化 SQL + 加索引。部署是手段,性能是目标,不能本末倒置

4.5 “修改 py 代码自动重启” 的正确姿势

热词里高频问 “gunicorn 修改py代码自动重启”,但生产环境严禁--reload!因为:

  • --reload会监控所有.py文件,包括settings.py,一旦改错配置,Gunicorn 会反复崩溃重启。
  • 它用inotify,在高 IO 服务器上可能漏事件,导致不重启。
  • 它不支持 graceful shutdown,正在处理的请求会被中断。

正确流程是:

  1. 修改代码,git commit -m "fix bug"
  2. git pull拉取最新代码
  3. python manage.py migrate(如有新 migration)
  4. python manage.py collectstatic --noinput
  5. sudo systemctl restart gunicorn
    systemd 会发送SIGTERM给主进程,Gunicorn 先停止接受新请求,等所有 worker 处理完当前请求后,再退出,全程无请求丢失。

提示:可以写一个一键部署脚本deploy.sh,把步骤 2–5 封装起来,每次上线只需./deploy.sh。这才是工程师该有的效率。

5. 常见问题与排查技巧实录:那些凌晨三点的告警电话

5.1 典型问题速查表

现象可能原因快速验证命令解决方案
浏览器打不开,显示This site can’t be reachedNginx 未运行,或防火墙拦截sudo systemctl status nginxsudo ufw statussudo systemctl start nginxsudo ufw allow 'Nginx Full'
打开页面显示502 Bad GatewayGunicorn 未运行,或 socket 文件权限错误sudo systemctl status gunicornls -l /run/gunicorn.socksudo systemctl start gunicornsudo chown webapp:www-data /run/gunicorn.sock
Admin 登录后 500,日志报relation "auth_user" does not exist数据库未迁移sudo -u webapp python /home/webapp/mysite/manage.py migrate运行迁移命令
静态文件 404,但collectstatic已执行Nginxalias路径错误,或STATIC_ROOT配置错ls /home/webapp/mysite/static/admin/;检查settings.pySTATIC_ROOT确保alias指向STATIC_ROOT目录,且目录存在
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failedPostgres 服务未启动,或pg_hba.conf拒绝连接sudo systemctl status postgresqlsudo cat /etc/postgresql/*/main/pg_hba.conf | grep mysite_usersudo systemctl start postgresql;确认pg_hba.confhost mysite_db mysite_user 127.0.0.1/32 md5

5.2 独家避坑技巧:书本里不会写的实战经验

技巧一:用strace抓 Gunicorn 启动失败的根因
有时systemctl status gunicorn只显示failed,日志为空。这时用strace

sudo strace -f -e trace=execve -s 1000 /home/webapp/mysite_env/bin/gunicorn --bind unix:/run/gunicorn.sock mysite.wsgi:application

它会打印出 Gunicorn 尝试执行的每一个系统调用。如果看到execve("/home/webapp/mysite_env/bin/python", ...)后报No such file or directory,说明虚拟环境损坏,需重装venv

技巧二:Nginx 502 时,用netstat确认 socket 是否被监听

sudo netstat -tulpn \| grep :8000 # 看 TCP 端口 sudo netstat -tulpn \| grep gunicorn.sock # 看 Unix socket

如果netstat没输出,证明 Gunicorn 根本没 bind 成功,不是 Nginx 配置问题。

技巧三:Postgres 连接数爆满,用pg_terminate_backend()紧急清理
psql -c "SELECT * FROM pg_stat_activity;"显示上百个idle in transaction状态时,执行:

SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND now() - state_change > interval '5 minutes';

这会杀掉空闲超 5 分钟的事务连接,立竿见影释放连接数。

技巧四:Django 日志不输出到文件?检查LOGGING配置和权限
settings.py中确保:

LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'INFO', 'class': 'logging.FileHandler', 'filename': '/home/webapp/mysite/logs/django.log', }, }, 'loggers': { 'django': { 'handlers': ['file'], '
http://www.gsyq.cn/news/1566332.html

相关文章:

  • 三维可视轨迹复盘 赋能港口应急处置、事故溯源与预案优化
  • WarcraftHelper:5个关键技巧让魔兽争霸3在现代电脑上流畅运行
  • 青岛黄金回收全攻略:6月行情解读与6家正规机构横向评测 - 余生黄金回收
  • 如何为Unity游戏构建智能实时翻译系统:XUnity.AutoTranslator深度解析
  • Ubuntu 20.04 安装 Composer 正确姿势:PHAR 校验与安全部署
  • 杭州上城区黄金回收五维测评及6家机构解析 - 上门黄金回收
  • 3分钟解密网易云音乐NCM格式:ncmdumpGUI图形化工具完整指南
  • 2026韶关黄金回收市场实地评测:六家正规门店信息与避坑要点 - 余生黄金回收
  • 台州评价高的贴汽车膜、贴车衣、防晒车窗膜哪家好,膜一姐怎么样,可以选吗?高性价比,口碑出众! - 汽车新知百晓生
  • Ubuntu 20.04升级本质:GNOME 3.36、systemd-resolved与Python 3.8迁移实战
  • Wireshark实战:HTTP登录抓包分析,揭示网络通信安全风险
  • 2026马鞍山美度市萧邦+劳力士手表专业回收,26年精选回收店铺排行榜推荐 - 谊识预商贸
  • 昆明盘龙区黄金回收五维测评指南与六家机构详情 - 上门黄金回收
  • SAGER框架:基于元学习的自进化推荐系统核心原理与实践
  • 2026 年 6 月劳力士官方维保网点真伪核验全记录,线下实地走访多方信息核对 - 劳力士中国服务中心
  • Video-subtitle-extractor深度解析:基于深度学习的视频硬字幕提取技术实现
  • 国产大模型实战指南:豆包、Kimi、DeepSeek、通义千问场景选型手册
  • 开源大模型本地部署:Hugging Face下载、量化与推理框架实战指南
  • 武汉江汉区黄金回收防坑 当前金价904元每克 - 上门黄金回收
  • 抖音主播加入哪家公会合适 - 舒雯文化
  • QLoRA微调大模型实战:用100条工艺数据训一个“半导体专家“一、问题背景:通用大模型不懂FAB,微调也太贵
  • 终极QQ音乐解密指南:qmcdump让你轻松解锁加密音乐文件
  • 2026肇庆黄金回收实用手册:价格走势与六家正规门店 - 余生黄金回收
  • 无锡锡山区黄金回收指南:当前金价与6家回收机构对比 - 上门黄金回收
  • 2026年6月最新!百达翡丽官方维修门店地址完整发布,全新全国统一售后热线同步开通 - 百达翡丽中国服务中心
  • 巴彦淖尔市奢侈品手表包包出手怎么卖高价?5家本地回收店实地询价分享 - 谊识预商贸
  • 在威联通NAS上用Docker部署OpenClaw实现本地AI自动化
  • 2026肇庆黄金回收市场实测:六家实体门店服务与避坑 - 余生黄金回收
  • 切片最优传输的摊销优化:RA-OT与OA-OT原理及在WGAN中的应用
  • 0621晨间日记