{T}

回滚与运行手册

本文档合并原「版本回滚策略」与「运行手册」两篇,聚焦 Python 服务生产环境的恢复动作与日常运行 SOP:当线上版本出问题如何安全回滚,以及服务启停、健康检查与故障排查的标准操作。

常规发布与部署流程请查看 云部署实战;CI/CD 流水线见 CI/CD Python 项目。

1. 版本回滚策略

1.1 回滚决策流程

图表渲染中…

1.2 回滚原则

  • 生产环境仅允许回滚到已验证、可追溯的构建产物(Docker 镜像 tag 或 git tag)。
  • 回滚不应直接修改源分支,避免在应急处理中引入新的不可追踪变更。
  • 回滚后必须重新验证健康检查、核心 API 和关键页面。
  • 数据库迁移回滚需格外谨慎——优先选择向后兼容的迁移设计

1.3 回滚操作

Docker 镜像回滚(推荐)

bash
# 查看可用版本
docker images | grep app

# 回滚到上一稳定版本
cd /opt/app
export APP_VERSION=v1.2.3  # 上一稳定版本 tag
docker compose pull
docker compose up -d --no-deps app celery

# 验证
sleep 10
curl -sf http://localhost:8000/health || echo "ROLLBACK FAILED"

Git 回滚(裸机部署)

bash
cd /opt/app

# 查看最近 tag
git tag --sort=-creatordate | head -5

# 回滚到上一 tag
git checkout v1.2.3

# 重装依赖(如有变更)
pip install -r requirements/prod.txt

# 重启服务
sudo systemctl restart app celery

数据库迁移回滚

高风险操作

数据库迁移回滚可能导致数据丢失。执行前必须备份。

bash
# 查看当前迁移状态
python manage.py showmigrations

# 备份数据库
pg_dump -U app app_db > /backup/app_db_$(date +%Y%m%d_%H%M%S).sql

# 回滚到指定迁移(Django)
python manage.py migrate app_name 0005_previous_migration

# 回滚全部迁移(极端情况)
python manage.py migrate app_name zero

向后兼容迁移设计原则:

操作安全做法危险做法
删除列先停止读写 → 下版本再删直接 DROP COLUMN
重命名列新增列 → 双写 → 迁移数据 → 删旧列直接 RENAME
修改类型新增列 → 迁移 → 切换 → 删旧列直接 ALTER TYPE

1.4 回滚验证清单

  • /health 端点返回 200
  • 核心 API 响应正常(登录/列表/详情)
  • 错误率恢复到基线水平(< 0.1%)
  • 无新增 Sentry 告警
  • Celery 任务队列无堆积
  • 数据库连接数正常

1.5 事故记录模板

markdown
## 事故报告 - YYYY-MM-DD

**影响时间**:HH:MM ~ HH:MM(共 X 分钟)
**影响范围**:[描述受影响的功能/用户群]
**根因**:[简述根本原因]
**回滚版本**:v1.2.3 → v1.2.2
**处理过程**:
1. HH:MM 发现异常
2. HH:MM 确认需要回滚
3. HH:MM 执行回滚
4. HH:MM 验证恢复
**后续改进**:[防止复发的措施]

2. 运行 SOP

2.1 环境准备

系统要求

组件最低版本推荐版本
Python3.103.12+
pip23.024.0+
PostgreSQL1416
Redis6.07.2
Nginx1.201.26

虚拟环境初始化

bash
# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate  # Linux/macOS
# .venv\Scripts\activate   # Windows

# 安装依赖
pip install -r requirements/prod.txt

# 验证安装
python -c "import sys; print(sys.version)"
pip check  # 检查依赖冲突

环境变量配置

bash
# .env 文件(禁止提交到版本控制)
DATABASE_URL=postgresql://user:pass@localhost:5432/app_db
REDIS_URL=redis://localhost:6379/0
SECRET_KEY=your-256-bit-secret-key
DEBUG=false
ALLOWED_HOSTS=example.com,www.example.com
SENTRY_DSN=https://xxx@sentry.io/xxx

2.2 服务启停

开发环境

bash
# 启动开发服务器(Django)
python manage.py runserver 0.0.0.0:8000

# 启动开发服务器(FastAPI)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

# 启动 Celery Worker
celery -A tasks worker --loglevel=info --concurrency=4

# 启动 Celery Beat(定时任务)
celery -A tasks beat --loglevel=info

生产环境(Gunicorn + Uvicorn)

bash
# 启动应用(WSGI)
gunicorn app.wsgi:application \
  --workers 4 \
  --worker-class gthread \
  --threads 2 \
  --bind 0.0.0.0:8000 \
  --timeout 120 \
  --access-logfile /var/log/app/access.log \
  --error-logfile /var/log/app/error.log

# 启动应用(ASGI - FastAPI)
gunicorn app.main:app \
  --workers 4 \
  --worker-class uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:8000

# 优雅重启(不中断连接)
kill -HUP $(cat /var/run/app/gunicorn.pid)

# 优雅停止
kill -TERM $(cat /var/run/app/gunicorn.pid)

Systemd 服务管理

ini
# /etc/systemd/system/app.service
[Unit]
Description=Python Web Application
After=network.target postgresql.service redis.service

[Service]
User=www-data
Group=www-data
WorkingDirectory=/opt/app
Environment="PATH=/opt/app/.venv/bin"
ExecStart=/opt/app/.venv/bin/gunicorn app.wsgi:application --workers 4 --bind 127.0.0.1:8000
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
bash
sudo systemctl daemon-reload
sudo systemctl enable app
sudo systemctl start app
sudo systemctl status app

2.3 健康检查

检查清单

bash
# 应用存活检查
curl -s http://localhost:8000/health | python -m json.tool

# 数据库连接检查
python -c "
import psycopg2
conn = psycopg2.connect('dbname=app_db user=app')
cur = conn.cursor()
cur.execute('SELECT 1')
print('DB OK:', cur.fetchone())
conn.close()
"

# Redis 连接检查
redis-cli ping  # 应返回 PONG

# Celery Worker 状态
celery -A tasks inspect ping

# 磁盘空间
df -h /var/log /opt/app

# 内存使用
free -h
ps aux --sort=-%mem | head -10

日志排查

bash
# 查看最近错误
tail -100 /var/log/app/error.log | grep -i "error\|traceback"

# 实时跟踪
tail -f /var/log/app/access.log

# 按时间范围查询
awk '/2026-07-31 10:00/,/2026-07-31 11:00/' /var/log/app/error.log

# 统计 5xx 错误
grep " 5[0-9][0-9] " /var/log/app/access.log | wc -l

2.4 常见故障处理

症状可能原因处理步骤
502 Bad Gateway应用进程崩溃/未启动systemctl status app → 查看 error.log → 重启
响应缓慢DB 慢查询/连接池耗尽检查 pg_stat_activity → 优化查询/增大连接池
OOM Killed内存泄漏/Worker 过多`dmesg
Celery 任务堆积Worker 不足/任务阻塞celery inspect active → 增加 concurrency
连接超时Redis/DB 不可达redis-cli ping / pg_isready → 检查网络/防火墙

3. 相关页面