From f948a410b67097db114ce1d86b7eb310a446148d Mon Sep 17 00:00:00 2001 From: cnbugs Date: Mon, 10 Aug 2026 23:06:28 +0800 Subject: [PATCH] =?UTF-8?q?ops:=20=E6=8A=8A=20systemd=20unit=20=E7=BA=B3?= =?UTF-8?q?=E5=85=A5=E7=89=88=E6=9C=AC=E6=8E=A7=E5=88=B6,=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=20timeout/=E9=99=90=E6=B5=81/=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 背景: 生产机 /etc/systemd/system/socks-manager.service 长期脱管:参数跟 README 文档不一致(-w 2 vs -w 1), 也没有 -w 4 的孤儿 gunicorn 抢占 5000 端口、 systemd 启不来服务。已删孤儿, 改用本仓库的 unit 作为 唯一权威源。 变更: + deploy/socks-manager.service 单元文件唯一权威源 + deploy/install.sh 一键同步: install + daemon-reload + enable + restart + 验证 active M README.md 部署章节改为引用 deploy/, 删除内联 unit 代码(避免再次漂移) 调优: - --timeout 30 网络扫描器半截请求占满 worker, 30s 及时回收 - --max-requests 1000 周期性回收 worker, 防内存泄漏 - --limit-request-line 防御大请求行导致 worker 长时间阻塞 - MemoryMax=512M cgroup 硬上限, 防单 worker 把整台 1GB VPS 拖死再拖到 OOM - LimitNOFILE=65535 SOCKS5 大并发客户端连接所需 - Type=notify + 保留 Restart=always / RestartSec=5 --- README.md | 73 +++++++++++++++--------------------- deploy/install.sh | 43 +++++++++++++++++++++ deploy/socks-manager.service | 63 +++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 43 deletions(-) create mode 100755 deploy/install.sh create mode 100644 deploy/socks-manager.service diff --git a/README.md b/README.md index ed9d009..ae5633d 100644 --- a/README.md +++ b/README.md @@ -187,66 +187,53 @@ Flask 内置开发服务器不适合生产环境。使用 **Gunicorn**(生产 # 安装 gunicorn pip install gunicorn --break-system-packages -# 启动(4 worker 进程,适合 4 核服务器) -gunicorn -w 4 -b 0.0.0.0:5000 --timeout 120 run:app +# 最小启动(不推荐生产,worker 数量 = CPU 核心数,单核机器用 -w 1) +gunicorn -w 1 -b 0.0.0.0:5000 run:app -# 推荐参数(更长超时 + 优雅关闭) -gunicorn -w 2 -b 0.0.0.0:5000 \ - --timeout 300 \ +# 推荐参数:30s 超时 + 优雅关闭 + 周期性回收 worker 防内存泄漏 +gunicorn -w 1 -b 0.0.0.0:5000 \ + --timeout 30 \ --graceful-timeout 30 \ - --max-requests 10000 \ - --max-requests-jitter 1000 \ + --max-requests 1000 \ + --max-requests-jitter 100 \ + --limit-request-line 8190 \ + --limit-request-fields 100 \ run:app ``` > **注意**:SOCKS5 代理实例运行在独立的 asyncio 线程中,不受 Gunicorn worker 数量影响。 +> **生产请用 systemd 托管**,见下节;裸 gunicorn 没有开机自启和崩溃重启。 --- ### 2. Systemd 服务配置(推荐) -创建 `/etc/systemd/system/socks-manager.service`: +服务单元文件的**唯一权威源**在仓库 `deploy/socks-manager.service`。 +所有参数、调优注释、`MemoryMax` 限制都集中在那一份,生产机只放一份拷贝。 -```ini -[Unit] -Description=SOCKS5 Proxy Manager -After=network.target +部署步骤: -[Service] -Type=notify -User=root -WorkingDirectory=/opt/socks-manager -Environment="PATH=/usr/local/bin:/usr/bin:/bin" - -# 生产环境变量(按需修改) -Environment="SM_ADMIN_PASSWORD=你的强密码" -Environment="SM_SECRET_KEY=生产环境用openssl rand -hex 32生成" -Environment="SM_LOG_LEVEL=WARN" -# Environment="SM_COOKIE_SECURE=true" # HTTPS 时开启 -# Environment="SM_SESSION_DOMAIN=你的域名或IP" # 跨域时设置 - -ExecStart=/usr/local/bin/gunicorn -w 2 -b 0.0.0.0:5000 \ - --timeout 300 \ - --graceful-timeout 30 \ - run:app - -# 优雅关闭:先给 SOCKS5 实例时间关闭活跃连接 -ExecStop=/bin/kill -s TERM $MAINPID -TimeoutStopSec=60 - -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target +```bash +# 1. 在本地修改 deploy/socks-manager.service +# 2. git commit + push +# 3. 在生产机 (/opt/socks-manager) 拉取并执行: +git pull +sudo bash deploy/install.sh ``` -启动服务: +`install.sh` 做的事:复制 unit 到 `/etc/systemd/system/` → `daemon-reload` → `enable` (开机自启) → `restart` → 等 15s 验证 active。 + +完整 unit 见 [`deploy/socks-manager.service`](deploy/socks-manager.service),关键参数说明: +- `-w 1` / `--timeout 30` / `--graceful-timeout 30` — 1 核 + 1GB 内存机型的基线,按 `nproc` 调整 `-w` +- `--max-requests 1000` + jitter — 周期性回收 worker 防内存泄漏 +- `MemoryMax=512M` — cgroup 硬上限,防整台 VPS 被拖死 +- `LimitNOFILE=65535` — SOCKS5 大并发客户端连接需要 + +常用命令: ```bash -systemctl daemon-reload -systemctl enable --now socks-manager systemctl status socks-manager -journalctl -u socks-manager -f # 查看实时日志 +journalctl -u socks-manager -f # 实时日志 +systemctl restart socks-manager # 改完代码后重启 ``` --- diff --git a/deploy/install.sh b/deploy/install.sh new file mode 100755 index 0000000..b348502 --- /dev/null +++ b/deploy/install.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# 把 deploy/socks-manager.service 同步到生产机并重启。 +# +# 使用: 在生产机 /opt/socks-manager 下执行 +# bash deploy/install.sh +# +# 假定: 仓库已 git pull 到最新,当前在 /opt/socks-manager 工作目录下。 + +set -euo pipefail + +SERVICE_FILE="deploy/socks-manager.service" +DEST="/etc/systemd/system/socks-manager.service" + +if [[ ! -f "$SERVICE_FILE" ]]; then + echo "ERROR: $SERVICE_FILE not found. Run from /opt/socks-manager." >&2 + exit 1 +fi + +echo "[1/5] install unit -> $DEST" +install -m 0644 "$SERVICE_FILE" "$DEST" + +echo "[2/5] daemon-reload" +systemctl daemon-reload + +echo "[3/5] enable (开机自启)" +systemctl enable socks-manager.service + +echo "[4/5] restart" +systemctl restart socks-manager.service + +echo "[5/5] wait for active (max 15s)" +for i in $(seq 1 15); do + if systemctl is-active --quiet socks-manager.service; then + echo "active after ${i}s" + systemctl status socks-manager.service --no-pager | head -15 + exit 0 + fi + sleep 1 +done + +echo "ERROR: service did not become active in 15s" >&2 +journalctl -u socks-manager.service -n 80 --no-pager >&2 +exit 1 diff --git a/deploy/socks-manager.service b/deploy/socks-manager.service new file mode 100644 index 0000000..950d147 --- /dev/null +++ b/deploy/socks-manager.service @@ -0,0 +1,63 @@ +# SOCKS Manager — systemd unit (authoritative source) +# +# 这个文件是服务器上 /etc/systemd/system/socks-manager.service 的唯一定义源。 +# 修改流程: +# 1. 编辑本文件 +# 2. 提交并 push 到 origin +# 3. 在生产机执行: bash deploy/install.sh +# +# 调优说明(按机器规格): +# -w N gunicorn worker 数。1 核 CPU 建议 1,2 核建议 2。 +# --timeout 30 HTTP 请求行/头/体的总超时(秒)。网络扫描器发 PRI * HTTP/2.0 这类 +# 半截请求会占满 worker,30s 既能容忍慢客户端也能及时回收。 +# --graceful-timeout 30 systemd 停止时给 worker 写完响应的最大等待时间。 +# --max-requests 1000 worker 处理 N 个请求后自杀重启,防止内存泄漏累积。 +# --max-requests-jitter 100 错峰重启,避免所有 worker 同时重启。 +# MemoryMax=512M cgroup 内存硬上限,超限立即 OOM kill,保护宿主机。 +# LimitNOFILE=65535 SOCKS5 代理每个实例一个监听 socket + 大量客户端连接, +# 默认 1024 远远不够。 + +[Unit] +Description=SOCKS5 Proxy Manager +After=network.target + +[Service] +Type=notify +User=root +WorkingDirectory=/opt/socks-manager +Environment="PATH=/usr/local/bin:/usr/bin:/bin" + +# 生产环境变量(按需修改)— 敏感信息建议放到 /opt/socks-manager/.env 或 +# /etc/socks-manager/socks-manager.env,用 EnvironmentFile= 引入,不要写进 git。 +Environment="SM_ADMIN_PASSWORD=test123" +Environment="SM_SECRET_KEY=xxxx111wwwddadljkkjkjnmooihjklhhgk" +Environment="SM_LOG_LEVEL=WARN" +# Environment="SM_COOKIE_SECURE=true" # HTTPS 时开启 +# Environment="SM_SESSION_DOMAIN=你的域名或IP" # 跨域时设置 + +ExecStart=/usr/local/bin/gunicorn \ + -w 1 \ + -b 0.0.0.0:5000 \ + --timeout 30 \ + --graceful-timeout 30 \ + --max-requests 1000 \ + --max-requests-jitter 100 \ + --limit-request-line 8190 \ + --limit-request-fields 100 \ + --limit-request-field_size 8190 \ + run:app + +# 优雅关闭:先给 SOCKS5 实例时间关闭活跃连接 +ExecStop=/bin/kill -s TERM $MAINPID +TimeoutStopSec=60 + +Restart=always +RestartSec=5 + +# 资源限制:1GB 内存的 VPS 单 worker 留 512M 足够,超了立刻被 OOM kill 而非慢慢拖死整机 +MemoryMax=512M +MemoryHigh=384M +LimitNOFILE=65535 + +[Install] +WantedBy=multi-user.target