181 lines
7.6 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# ════════════════════════════════════════════════════════════════
# 根据探测档位动态生成资源调优 · tune-from-env.sh
# Sovereign: TCS-0002∞ · 国作登字-2026-A-00037559
# 守护: 铸渊 · ICE-GL-ZY001
# ════════════════════════════════════════════════════════════════
#
# 读 detect-env.sh 写出的 server-env.json, 依据 size_tier 生成:
# 1. $DATA_ROOT/lighthouse/.env.tune — 决策快照
# 含 SIZE_TIER / PG_SHARED_BUFFERS / PG_WORK_MEM / PG_MAX_CONN
# / GITEA_CACHE_POOL / GITEA_QUEUE_LENGTH / RUNNER_DEFAULT_ENABLED
# 2. 决策回执 -> $DEPLOY_ROOT/_logs/tune-decision-*.json
#
# ⚠️ 当前 .env.tune 的真实作用域 (2026-05-08 修正, 别再被注释误导):
# .env.tune 不是 docker-compose 的 env_file. compose 启动时不会
# 自动读它 (docker-compose.yml 没有 env_file: .env.tune 声明).
#
# bootstrap.sh 会在调 docker compose up 之前 `source .env.tune`,
# **当前真正影响行为的只有 RUNNER_DEFAULT_ENABLED** — 它决定 update
# 阶段是否带 `--profile runner` 起 runner 容器.
#
# PG_SHARED_BUFFERS / PG_WORK_MEM / PG_MAX_CONN / GITEA_CACHE_POOL /
# GITEA_QUEUE_LENGTH 这些字段目前**只是档位决策的存档**, 写到 .env.tune
# 是为了:
# a) tune-decision-*.json 回执留痕 (霜砚 / 冰朔可追溯)
# b) 后续如果在 docker-compose.yml 加上 `env_file: ./.env.tune` +
# 在 postgres / gitea 服务里用 `${PG_SHARED_BUFFERS}` 引用,
# 这一份就立刻生效, 不用改 tune-from-env.sh
#
# 也就是说: 这个脚本现在做的事 = "决策 + 留档", 不是"实时调 PG".
# 要让 PG 调优真的生效, 需要在 docker-compose.yml 里手动加引用
# (TODO 见 §下方).
#
# 档位策略 (因果链):
# tiny <4G : runner 关掉, postgres shared_buffers=64M, gitea cache 减半
# small 4-6G : runner 关掉, postgres shared_buffers=128M
# medium 6-12G: runner=optional (默认关), postgres shared_buffers=256M
# large 12-24G: runner=on, postgres shared_buffers=512M
# xlarge >=24G: runner=on, postgres shared_buffers=1G
#
# 设计理念:
# 不再硬假设 4C16G. 2C8G 来了也能跑(只是 runner 默认关, 不会同时塞下);
# 8C32G 来了也能跑(自动放大 PG buffer). 这一层是"动态适配"的根基.
# ════════════════════════════════════════════════════════════════
set -euo pipefail
ENV_FILE="${ENV_FILE:-/opt/guanghu/_logs/server-env.json}"
DATA_ROOT="${DATA_ROOT:-/data}"
DEPLOY_ROOT="${DEPLOY_ROOT:-/opt/guanghu}"
if [ ! -f "$ENV_FILE" ]; then
echo "❌ [tune] 找不到 $ENV_FILE, 请先跑 detect-env.sh" >&2
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
echo "❌ [tune] 需要 jq (apt-get install -y jq)" >&2
exit 1
fi
SIZE_TIER="$(jq -r '.compute.size_tier' "$ENV_FILE")"
MEM_MB="$(jq -r '.compute.memory_total_mb' "$ENV_FILE")"
CPU="$(jq -r '.compute.cpu_count' "$ENV_FILE")"
# ─── 档位 → 参数表 ────────────────────────────────────────────
case "$SIZE_TIER" in
tiny)
PG_SHARED_BUFFERS="64MB"
PG_WORK_MEM="2MB"
PG_MAX_CONN="40"
GITEA_CACHE_POOL="50"
RUNNER_DEFAULT_ENABLED="false"
GITEA_QUEUE_LENGTH="100"
NOTE="资源极少, runner 必关, 不要同时跑大型 git push"
;;
small)
PG_SHARED_BUFFERS="128MB"
PG_WORK_MEM="4MB"
PG_MAX_CONN="60"
GITEA_CACHE_POOL="100"
RUNNER_DEFAULT_ENABLED="false"
GITEA_QUEUE_LENGTH="200"
NOTE="2C8G 档. Gitea+PG+Redis 能跑, runner 默认关 (按需手动 docker compose --profile runner up)"
;;
medium)
PG_SHARED_BUFFERS="256MB"
PG_WORK_MEM="8MB"
PG_MAX_CONN="100"
GITEA_CACHE_POOL="100"
RUNNER_DEFAULT_ENABLED="false"
GITEA_QUEUE_LENGTH="500"
NOTE="主流档. runner 默认关, 大型构建任务时再开"
;;
large)
PG_SHARED_BUFFERS="512MB"
PG_WORK_MEM="16MB"
PG_MAX_CONN="200"
GITEA_CACHE_POOL="200"
RUNNER_DEFAULT_ENABLED="true"
GITEA_QUEUE_LENGTH="1000"
NOTE="原计划 4C16G 主灯塔. runner 默认开"
;;
xlarge)
PG_SHARED_BUFFERS="1GB"
PG_WORK_MEM="32MB"
PG_MAX_CONN="300"
GITEA_CACHE_POOL="300"
RUNNER_DEFAULT_ENABLED="true"
GITEA_QUEUE_LENGTH="2000"
NOTE="超规格, 全部组件并行无忧"
;;
*)
echo "❌ [tune] 未知 size_tier=$SIZE_TIER" >&2
exit 1
;;
esac
# ─── 写 .env.tune (compose 第二份 .env) ───────────────────────
TUNE_FILE="$DATA_ROOT/lighthouse/.env.tune"
mkdir -p "$(dirname "$TUNE_FILE")"
cat > "$TUNE_FILE" <<EOF
# Generated by tune-from-env.sh @ $(date -u +%Y-%m-%dT%H:%M:%SZ)
# 档位: $SIZE_TIER (基于 ${MEM_MB}MB 内存 / ${CPU} 核)
# 注: $NOTE
#
# ⚠️ 作用域说明 (避免误判):
# - bootstrap.sh source 这个文件, 当前**只读 RUNNER_DEFAULT_ENABLED**,
# 用它决定是否带 --profile runner 启 runner 容器.
# - 下面的 PG_* / GITEA_* 字段是**档位决策的快照**, docker-compose.yml
# 当前并未通过 env_file 引用本文件, 所以这些值不会自动生效到 Postgres
# / Gitea 容器内. 它们的用途是: (a) 留档可追溯 (b) 未来在 compose 里
# 加引用就能立刻生效, 无需改本脚本.
SIZE_TIER=$SIZE_TIER
PG_SHARED_BUFFERS=$PG_SHARED_BUFFERS
PG_WORK_MEM=$PG_WORK_MEM
PG_MAX_CONN=$PG_MAX_CONN
GITEA_CACHE_POOL=$GITEA_CACHE_POOL
GITEA_QUEUE_LENGTH=$GITEA_QUEUE_LENGTH
RUNNER_DEFAULT_ENABLED=$RUNNER_DEFAULT_ENABLED
EOF
chmod 644 "$TUNE_FILE"
# ─── 决策回执 ─────────────────────────────────────────────────
TS="$(date -u +%Y%m%d-%H%M%S)"
RECEIPT="$DEPLOY_ROOT/_logs/tune-decision-$TS.json"
mkdir -p "$DEPLOY_ROOT/_logs"
cat > "$RECEIPT" <<EOF
{
"_sovereign": "TCS-0002∞ · 国作登字-2026-A-00037559",
"decided_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"input": {
"size_tier": "$SIZE_TIER",
"memory_mb": $MEM_MB,
"cpu_count": $CPU
},
"decision": {
"PG_SHARED_BUFFERS": "$PG_SHARED_BUFFERS",
"PG_WORK_MEM": "$PG_WORK_MEM",
"PG_MAX_CONN": $PG_MAX_CONN,
"GITEA_CACHE_POOL": $GITEA_CACHE_POOL,
"GITEA_QUEUE_LENGTH": $GITEA_QUEUE_LENGTH,
"RUNNER_DEFAULT_ENABLED": $RUNNER_DEFAULT_ENABLED
},
"note": "$NOTE",
"tune_file": "$TUNE_FILE"
}
EOF
echo "═══════════════════════════════════════════════════════════"
echo " [tune] 动态调优决策"
echo "═══════════════════════════════════════════════════════════"
echo " 档位: $SIZE_TIER (${MEM_MB}MB / ${CPU} 核)"
echo " PG shared_buf: $PG_SHARED_BUFFERS"
echo " PG max_conn: $PG_MAX_CONN"
echo " Gitea cache: $GITEA_CACHE_POOL"
echo " Runner 默认: $RUNNER_DEFAULT_ENABLED"
echo " 注: $NOTE"
echo " 写入: $TUNE_FILE"
echo " 回执: $RECEIPT"
echo "═══════════════════════════════════════════════════════════"