diff --git a/deploy/audit-system.sh b/deploy/audit-system.sh new file mode 100644 index 0000000..482123d --- /dev/null +++ b/deploy/audit-system.sh @@ -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" diff --git a/deploy/systemd/gunicorn-dianjing.service b/deploy/systemd/gunicorn-dianjing.service index 048b7e7..6b97642 100644 --- a/deploy/systemd/gunicorn-dianjing.service +++ b/deploy/systemd/gunicorn-dianjing.service @@ -7,7 +7,7 @@ Type=simple User=root Group=root 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 RestartSec=3 StandardOutput=null diff --git a/gunicorn.conf.py b/gunicorn.conf.py index e9550b9..ee5de2a 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -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" -# 工作进程数(根据CPU核心数调整,建议:CPU核心数*2+1) -# 查看CPU核心数:cat /proc/cpuinfo | grep "processor" | wc -l -workers = 4 +# 必须用 gthread:sync 模式下 4 worker 同时只能处理 4 个请求,远程 MySQL 一慢就全站卡死 +workers = 6 +threads = 4 +worker_class = "gthread" -# 工作模式(使用gevent支持异步,更高效) -#worker_class = "gevent" -worker_class = "sync" # 改成这个 - -# 每个worker的最大请求数(防止内存泄漏) -max_requests = 1000 -max_requests_jitter = 50 # 随机抖动,避免所有worker同时重启 - -# 超时时间(秒) -timeout = 30 +timeout = 120 +graceful_timeout = 30 keepalive = 2 -# 预加载应用(减少内存占用,加快请求处理) -preload_app = True +max_requests = 2000 +max_requests_jitter = 100 -# 日志配置 -# 访问日志:输出到标准输出,便于OnePanel查看 -accesslog = "-" -# 错误日志:输出到标准错误 -errorlog = "-" -# 日志级别 -loglevel = "info" +# 禁止输出到 stdout/stderr(曾灌满 journal 导致整机卡) +accesslog = None +errorlog = "/tmp/gunicorn-error.log" +loglevel = "warning" + +# gthread + MySQL 连接池:preload 易在 fork 后出连接问题 +preload_app = False -# 进程名称(便于识别) proc_name = "a_long_dianjing_gunicorn" - -# 工作进程的用户/组(安全考虑,用非root用户运行) -# user = "www-data" -# group = "www-data" - -# 工作进程临时目录(避免权限问题) worker_tmp_dir = "/dev/shm" +daemon = False -# 限制请求数据大小(防止大文件攻击) limit_request_line = 4094 limit_request_fields = 100 limit_request_field_size = 8190 - -# 优雅退出时间 -graceful_timeout = 30 - -# 进程守护(如果用systemd管理,这里设为False) -daemon = False \ No newline at end of file