fix: gunicorn.conf.py 从 sync 改为 gthread,修复全站卡死根因

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-09 05:07:06 +08:00
parent 5d20c1ed97
commit a48c9d3134
3 changed files with 56 additions and 39 deletions

37
deploy/audit-system.sh Normal file
View File

@@ -0,0 +1,37 @@
#!/bin/bash
# 系统级排查Gunicorn 是否双开、是否用了错误的 sync 配置
set -e
echo "========== Gunicorn 进程(看 worker_class / 是否双开)=========="
pgrep -af gunicorn || echo "无 gunicorn"
echo ""
echo "========== 8001 端口占用 =========="
ss -ltnp 2>/dev/null | grep 8001 || netstat -ltnp 2>/dev/null | grep 8001 || echo "8001 未监听"
echo ""
echo "========== systemd 实际启动命令 =========="
systemctl cat gunicorn-dianjing.service 2>/dev/null | grep -E '^ExecStart|^Environment' || echo "无 systemd service"
echo ""
echo "========== gunicorn.conf.py 关键项 =========="
CONF="/opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django/gunicorn.conf.py"
if [ -f "$CONF" ]; then
grep -E 'worker_class|workers|threads|accesslog|errorlog|preload' "$CONF" | grep -v '^#'
else
echo "找不到 $CONF"
fi
echo ""
echo "========== 判定 =========="
NG=$(pgrep -cf 'gunicorn.*a_long_dianjing' 2>/dev/null || echo 0)
if [ "$NG" -gt 8 ]; then
echo ">>> 警告: gunicorn 进程过多($NG),可能 systemd + 1Panel 双开,必须只留 systemd"
fi
if grep -q 'worker_class.*sync' "$CONF" 2>/dev/null; then
echo ">>> 致命: gunicorn.conf.py 仍是 sync全站会卡死必须改为 gthread 并 restart"
fi
if grep -q 'accesslog.*"-' "$CONF" 2>/dev/null || grep -q "accesslog = '-'" "$CONF" 2>/dev/null; then
echo ">>> 致命: accesslog 输出到 stdout会灌 journal 卡整机"
fi
echo ""
echo "正确做法: 1Panel 关闭 Python 自动管理 → git pull → bash deploy/safe-deploy.sh"

View File

@@ -7,7 +7,7 @@ Type=simple
User=root User=root
Group=root Group=root
WorkingDirectory=/opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django WorkingDirectory=/opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django
ExecStart=/usr/local/bin/gunicorn --bind 127.0.0.1:8001 --workers 6 --threads 4 --worker-class gthread --timeout 120 --log-level warning --access-logfile /dev/null --error-logfile /tmp/gunicorn-error.log a_long_dianjing.wsgi:application ExecStart=/usr/local/bin/gunicorn -c gunicorn.conf.py a_long_dianjing.wsgi:application
Restart=always Restart=always
RestartSec=3 RestartSec=3
StandardOutput=null StandardOutput=null

View File

@@ -1,52 +1,32 @@
# /opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django/gunicorn.conf.py # Gunicorn 生产配置systemd 与 1Panel 共用此文件,勿再手写冲突参数)
# 安装后: systemctl restart gunicorn-dianjing.service
# 绑定的IP和端口根据你的Nginx配置后端在8001端口
bind = "127.0.0.1:8001" bind = "127.0.0.1:8001"
# 工作进程数根据CPU核心数调整建议CPU核心数*2+1 # 必须用 gthreadsync 模式下 4 worker 同时只能处理 4 个请求,远程 MySQL 一慢就全站卡死
# 查看CPU核心数cat /proc/cpuinfo | grep "processor" | wc -l workers = 6
workers = 4 threads = 4
worker_class = "gthread"
# 工作模式使用gevent支持异步更高效 timeout = 120
#worker_class = "gevent" graceful_timeout = 30
worker_class = "sync" # 改成这个
# 每个worker的最大请求数防止内存泄漏
max_requests = 1000
max_requests_jitter = 50 # 随机抖动避免所有worker同时重启
# 超时时间(秒)
timeout = 30
keepalive = 2 keepalive = 2
# 预加载应用(减少内存占用,加快请求处理) max_requests = 2000
preload_app = True max_requests_jitter = 100
# 日志配置 # 禁止输出到 stdout/stderr曾灌满 journal 导致整机卡)
# 访问日志输出到标准输出便于OnePanel查看 accesslog = None
accesslog = "-" errorlog = "/tmp/gunicorn-error.log"
# 错误日志:输出到标准错误 loglevel = "warning"
errorlog = "-"
# 日志级别 # gthread + MySQL 连接池preload 易在 fork 后出连接问题
loglevel = "info" preload_app = False
# 进程名称(便于识别)
proc_name = "a_long_dianjing_gunicorn" proc_name = "a_long_dianjing_gunicorn"
# 工作进程的用户/组安全考虑用非root用户运行
# user = "www-data"
# group = "www-data"
# 工作进程临时目录(避免权限问题)
worker_tmp_dir = "/dev/shm" worker_tmp_dir = "/dev/shm"
daemon = False
# 限制请求数据大小(防止大文件攻击)
limit_request_line = 4094 limit_request_line = 4094
limit_request_fields = 100 limit_request_fields = 100
limit_request_field_size = 8190 limit_request_field_size = 8190
# 优雅退出时间
graceful_timeout = 30
# 进程守护如果用systemd管理这里设为False
daemon = False