跳到主要内容

线上故障应急

问题

Python 服务线上故障时如何快速止血和定位?应急响应的标准流程是什么?

答案

应急流程

快速止血手段

# 1. 回滚到上一个稳定版本
git revert HEAD
# 或 K8s 回滚
kubectl rollout undo deployment/myapp

# 2. 重启服务
sudo systemctl restart myapp
# 或 Gunicorn 优雅重启
kill -HUP $(cat /var/run/gunicorn.pid)

# 3. 扩容(应对流量突增)
kubectl scale deployment/myapp --replicas=10

排查工具集

# 查看进程状态
ps aux | grep python
top -p $(pgrep -f myapp)

# 查看端口和连接
ss -tlnp | grep 8000
ss -s # 连接数统计

# 查看磁盘
df -h
du -sh /var/log/*

# 查看 OOM
dmesg | grep -i oom
journalctl -u myapp --since "1 hour ago"

# Python 进程分析
py-spy dump --pid <PID> # 查看线程状态
py-spy record -o profile.svg --pid <PID> # 火焰图

常见故障场景

cases/common_issues.py
# 场景 1:连接池耗尽
# 症状:接口超时,日志 "QueuePool limit exceeded"
# 原因:连接未释放或并发超过连接池大小
# 修复:
engine = create_engine(
url,
pool_size=20, # 增大连接池
max_overflow=10, # 允许临时超额
pool_pre_ping=True, # 检测断连
pool_recycle=3600, # 1 小时回收
)

# 场景 2:内存持续增长
# 症状:RSS 不断增长,最终 OOM
# 快速止血:重启 + max_requests 定期重启 Worker
# 排查:tracemalloc 对比快照

# 场景 3:CPU 100%
# 症状:接口响应慢,Worker 不响应
# 排查:py-spy dump 查看 CPU 在哪
# 常见原因:正则回溯、死循环、GIL 竞争

降级开关

degradation.py
import redis

class FeatureFlag:
def __init__(self, redis_client: redis.Redis):
self.redis = redis_client

def is_enabled(self, feature: str) -> bool:
return self.redis.get(f"feature:{feature}") == b"1"

# 使用
flag = FeatureFlag(redis_client)

@app.get("/recommendations")
async def get_recommendations(user_id: int):
if not flag.is_enabled("recommendation_service"):
# 降级:返回热门推荐
return {"items": get_hot_items(), "source": "fallback"}
return {"items": await recommendation_service.get(user_id)}

复盘模板

## 故障复盘

**故障时间**:2024-01-15 14:00 ~ 14:30
**影响范围**:全站接口 5xx 错误率 30%
**故障等级**:P1

### 时间线
- 14:00 监控告警(错误率异常)
- 14:03 值班同学响应
- 14:05 确认故障,执行回滚
- 14:10 回滚完成,错误率下降
- 14:30 完全恢复

### 根因
发布了新版本,数据库迁移脚本锁表导致查询超时。

### 改进措施
1. 数据库迁移添加 lock_timeout
2. 发布流程增加 canary 阶段
3. 完善监控告警(数据库慢查询)

常见面试问题

Q1: 如何判断是否需要回滚?

答案

  • 错误率 >5% 且持续上升 → 立即回滚
  • 只影响特定功能 → 关闭该功能的 Feature Flag
  • 原因明确且可快速修复 → 热修复 + 上线

Q2: 复盘要关注什么?

答案

  1. 根因而非表面原因(5 个 Why)
  2. 时间线:发现到恢复花了多久,哪里可以缩短
  3. 改进措施:每条要有负责人和 deadline
  4. 无责文化:复盘目的是改进,不是追责

Q3: 如何预防线上故障?

答案

阶段措施
开发Code Review、单元测试
部署灰度发布、Canary
运行监控告警、自动扩容
故障自动回滚、降级开关

相关链接