Files
getDomain/docs/18_domainCheck_CentOS9一键复制部署与更新文档.md
Your Name 0e096947fc debug
2026-04-17 15:13:46 +08:00

30 KiB
Raw Permalink Blame History

18 domainCheck CentOS9 全自动一键部署与更新文档

一、文档用途

这份文档只做一件事:

给你一套可以直接复制执行的命令,完成 1 台国外机器 + 2 台国内机器 的傻瓜式部署和后续更新。

文档边界:

统一前提:

  • 系统:CentOS Stream 9
  • 代码管理:统一 git
  • API 域名:api.domain.com
  • 后台域名:admin.domain
  • 分支:默认 main
  • 脚本约定:所有一键 .sh 只做部署,不执行任何 git 命令

目标机器:

  • 国外机器 1
    • 角色:overseas-control
  • 国内机器 2
    • mainland-controller-01
    • mainland-worker-01

一句话部署口径:

  • 国外机器:宝塔管理 Nginx / PostgreSQL / Redis + systemd 管理项目服务
  • 国内机器:纯 systemd 执行节点,不装宝塔

二、先改这里

正式执行本文命令前,先把下面这些变量替换成你自己的真实值。

API_DOMAIN=api.domain.com
ADMIN_DOMAIN=admin.domain

DB_NAME=domain
DB_USER=domainuser
DB_PASSWORD=请改成你的强密码

SYNC_SHARED_TOKEN=请改成你的共享令牌

OVERSEAS_NODE_CODE=overseas-control-01
MAINLAND_CONTROLLER_NODE_CODE=mainland-controller-01
MAINLAND_WORKER_NODE_CODE=mainland-worker-01

MAINLAND_CONTROLLER_IP=国内controller机器IP

NODE_VERSION=20
NODE_NVM_DIR=

最少必须先替换这 5 个:

  • DB_PASSWORD
  • REDIS_PASSWORD
  • SYNC_SHARED_TOKEN
  • API_DOMAIN
  • ADMIN_DOMAIN
  • MAINLAND_CONTROLLER_IP

如果你用 root 执行一键脚本,但 nvm 实际装在别的用户目录下,再额外补一个:

  • NODE_NVM_DIR

例如:

NODE_NVM_DIR=/home/www/.nvm

三、统一约定

1. 仓库目录

/www/wwwroot/getDomain

2. 运行目录

/opt/domaincheck

3. 统一更新命令

后续所有机器代码更新统一执行:

cd /www/wwwroot/getDomain
git fetch --all
git checkout main
git pull --ff-only origin main

3.1 首次全新机器先做什么

如果这台机器是第一次部署,而且本机还没有:

/www/wwwroot/getDomain

那么要先手动拉一次代码,因为脚本文件本身也在仓库里。

首次最小步骤:

mkdir -p /www/wwwroot
cd /www/wwwroot
git clone 你的仓库地址 getDomain
cd getDomain
git checkout main
git pull --ff-only origin main

然后再:

  1. 复制对应的 .conf.example
  2. 编辑 .conf
  3. 执行对应的 .sh

关键结论:

  • 新机器第一次:必须先手动 git clone
  • 后续每次更新:先手动 git pull
  • 后续执行脚本:不负责 clone,也不负责 pull
  • 脚本只负责“基于当前仓库代码做部署或更新”

3.2 这些命令用哪个用户执行

结论:

  • 整套部署命令建议统一使用 root
  • 不建议用 www 执行部署脚本
  • 但前端 npm installnpm run build 会由脚本自动切到仓库属主执行

原因:

  • 脚本会写:
    • /etc/default/...
    • /etc/systemd/system/...
    • /opt/domaincheck/...
  • 脚本会执行:
    • systemctl enable
    • systemctl restart
    • chown
    • 可能还有 dnf

这些都属于 root 口径,不适合 www 用户执行。

补充说明:

  • 脚本入口仍然是 root
  • 但国外机的一键脚本内部会自动识别仓库属主
  • 然后把前端构建切到仓库属主执行
  • 这样可以避免把 node_modulesdist、源码目录权限烧成 root
  • /etc/default/domaincheck-api 里的 CORS_ORIGINS 必须使用 JSON 数组格式
  • 正确示例:
    • CORS_ORIGINS='["https://admin.domain","http://127.0.0.1:3201","http://localhost:3201"]'
  • 不能写成逗号拼接字符串:
    • CORS_ORIGINS=https://admin.domain,http://127.0.0.1:3201,http://localhost:3201

最稳的执行方式:

sudo -i

然后再继续后面的复制、编辑和执行脚本。

4. 统一软链接

所有机器都统一建立:

mkdir -p /opt/domaincheck
ln -sfn /www/wwwroot/getDomain/domain-api /opt/domaincheck/domain-api
ln -sfn /www/wwwroot/getDomain/domain-web /opt/domaincheck/domain-web
ln -sfn /www/wwwroot/getDomain/domainCheck /opt/domaincheck/domainCheck

5. 并发配置约定

  • 默认检测并发由后台系统设置里的 默认检测线程数 控制
  • 若某台机器需要单独并发,可在后台系统设置里增加 节点独立线程覆盖
  • 远端日志回传由后台 系统设置 -> 运行配置检测控制 顶部按钮控制
    • 关闭回传
      • 不追加远端 Worker 日志镜像
      • 适合正式长期运行,减少额外事件写入
    • 关键回传
      • 只回传启动、停止、代理刷新、批次完成、异常、完成等关键过程
      • 适合大多数联调和线上观察
    • 全量回传
      • 在关键模式基础上,额外回传取任务、建线程、线程数变化、域名开始/完成/失败等过程
      • 适合临时排查问题,定位完成后建议切回 关键关闭
  • 检测控制页日志窗口现在会合并展示:
    • controller 本机可见的 Worker 日志尾部
    • 远端 Worker 回传的流程事件日志
  • 如果开启了远端日志回传但页面仍无新增输出,优先检查:
    • domaincheck-worker 是否已更新到最新代码
    • Worker 是否能连上 Redis
    • 检测任务是否由当前控制面发起,并带有 job_id / cycle_token
  • 规则是:
    • 节点已单独配置:走该节点自己的线程数
    • 节点未单独配置:回退到默认线程数
  • 节点编码必须和该机器 /etc/default/domaincheck-worker 里的 NODE_CODE 一致
  • 配置会同时写入:
    • Redisdomain_tool:thread_count
    • Redisdomain_tool:node_thread_counts
    • 本地文件:thread_count.json
    • 本地文件:node_thread_counts.json

6. 宝塔与 nvm 口径

  • 国外主控机:
    • 你如果已经长期用宝塔管理 PostgreSQLRedisNginx,可以继续用
    • domain-apidomaincheck-workerdomaincheck-sync-agent 仍建议走 systemd
  • 国内机器:
    • 不建议为了纯 worker 节点额外安装宝塔
    • 原因不是不能用,而是会多一层面板进程、端口、权限和故障面
    • 国内机器的最佳形态是:
      • 只装 Python 运行环境
      • 只装项目代码
      • 只跑 domaincheck-worker
      • 若是 controller再加 domaincheck-sync-agent
  • Node
    • 继续用 nvm 没问题,不需要改成系统全局安装
    • 建议统一到 Node 20
    • 生产构建时只要保证执行构建命令前已经 nvm use 20

6.1 nvm 安装命令

如果机器还没有安装 nvm,先执行:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

nvm -v
nvm install 20
nvm use 20

补充说明:

  • 国外机器如果要构建前端,必须先确保 nvm 可用
  • 一键部署脚本会调用 nvm install 20nvm use 20
  • 前端构建由仓库属主执行,不是由 root 直接执行
  • 如果你用 root 执行脚本,而 nvm 实际装在别的用户目录下:
    • 不需要改成 www 执行脚本
    • 直接在 install_overseas_quick.conf 里填写:
      • NODE_NVM_DIR=/home/www/.nvm
  • 当前一键脚本会按这个顺序找 Node 运行环境:
    • NODE_NVM_DIR
    • 当前环境变量里的 NVM_DIR
    • /root/.nvm
    • /home/www/.nvm
    • /www/server/nvm
    • /usr/local/nvm
    • 最后再尝试系统全局 nodenpm

6.2 国内机器已经装了宝塔怎么办

结论:

  • 不需要为了接入 controller / worker 专门重装系统
  • 机器上已经有宝塔,不等于这台机器不能继续用
  • 关键不是“有没有宝塔”,而是“不要让宝塔深度接管项目服务”

推荐做法:

  • 保留宝塔本身
  • 如果你已经习惯用宝塔管理:
    • PostgreSQL
    • Redis
    • 防火墙 / 端口
    • 证书 这些可以继续保留
  • 但项目服务仍然统一交给 systemd
    • domaincheck-worker
    • domaincheck-sync-agent
  • 不要把这些项目服务交给宝塔的守护进程或计划任务反复接管

对于国内 controller

  • 已装宝塔可以继续用
  • Redis / PostgreSQL 可以继续由宝塔安装和管理
  • domaincheck-worker / domaincheck-sync-agent 仍建议走 systemd

对于国内 worker

  • 已装宝塔也不用重装
  • 但尽量不要再给它额外配置站点、反代、复杂 PHP/Node 面板功能
  • 把它当普通 Linux 节点使用即可
  • 核心目标就是稳定运行 domaincheck-worker

只有在下面这些情况,才建议考虑重装:

  • 机器上历史站点和旧服务太多,端口冲突严重
  • Redis / PostgreSQL / Nginx 已经被旧项目改得很乱
  • 系统里残留环境过多,你自己也不再信任这台机器的稳定性

如果只是“已经装了宝塔”,但系统仍然清晰可控,就不建议为了这个项目重装。

7. 你实际应该怎么选

  • 如果国外主控机已经是宝塔机:
    • 继续沿用宝塔即可
    • 宝塔负责:
      • Nginx
      • PostgreSQL
      • Redis
      • SSL 证书
    • 项目自身服务继续交给:
      • domaincheck-api.service
      • domaincheck-worker.service
  • 如果国内机器只是跑检测:
    • 不要装宝塔
    • 直接按本文的纯命令部署
    • 这样最轻、最稳、最容易横向复制

8. Python 3.11 必须单独安装

  • 这里不能只依赖系统默认 python3
  • 必须明确安装 python3.11
  • 因为本文后续所有部署命令都直接使用:
    • python3.11 -m venv .venv

安装命令:

dnf install -y python3.11 python3.11-devel

安装后先验证:

python3.11 --version

期望输出类似:

Python 3.11.x

8.1 Linux 依赖安装特别说明

domainCheck/requirements.txt 是从桌面版沿用过来的,里面包含 Windows 专用依赖,例如:

  • pywin32
  • pywin32-ctypes
  • twisted-iocpsupport
  • win32-setctime

这些包在 Linux 上不能直接安装。

现在的 3 个一键部署脚本已经内置了兼容处理:

  • 会自动读取 domainCheck/requirements.txt
  • 自动生成 requirements.linux.txt
  • 自动过滤掉 Windows-only 依赖
  • 然后再执行 Linux 环境安装

所以现在在 Linux 上看到这类报错时,正确处理方式不是手工删仓库依赖,而是:

  1. git pull
  2. 确认脚本已经更新到最新版本
  3. 重新执行一键部署脚本

如果你是手工部署,不走一键脚本,那就不要直接跑:

pip install -r requirements.txt

而应该改成:

cd /opt/domaincheck/domainCheck
python3.11 - <<'PY'
from pathlib import Path

source = Path("requirements.txt")
target = Path("requirements.linux.txt")
raw = source.read_bytes()
for encoding in ("utf-8", "utf-16", "utf-16-le", "utf-16-be", "gbk"):
    try:
        text = raw.decode(encoding)
        break
    except UnicodeDecodeError:
        continue
else:
    raise SystemExit("无法解析 requirements.txt 编码")

skip_prefixes = (
    "pywin32==",
    "pywin32-ctypes==",
    "twisted-iocpsupport==",
    "win32-setctime==",
)
lines = []
for line in text.splitlines():
    normalized = line.strip().lstrip("\ufeff")
    if normalized.lower().startswith(skip_prefixes):
        continue
    lines.append(normalized)

target.write_text("\n".join(lines) + "\n", encoding="utf-8")
PY

source .venv/bin/activate
pip install -r requirements.linux.txt

四、最短复制块

这一节给你三段最短命令。

用法:

  • 急着部署时,先用这里
  • 想看每一步解释,再看后面的完整章节

1. 国外主控机最短复制块

先把下面 5 个值替换掉再执行:

API_DOMAIN
ADMIN_DOMAIN
DB_PASSWORD
OVERSEAS_NODE_CODE
NODE_VERSION

也可以直接改脚本头部变量后执行:

cp /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_overseas_quick.conf.example \
   /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_overseas_quick.conf

# 先编辑 install_overseas_quick.conf
bash /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_overseas_quick.sh

注意:

  • 这条脚本不会执行 git fetch
  • 这条脚本不会执行 git pull
  • 你要先自己把 /www/wwwroot/getDomain 更新到目标版本,再跑脚本
  • 这条脚本会自动过滤 Windows-only Python 依赖
  • 这条脚本会自动把 CORS_ORIGINS 写成 systemd 可用的安全格式
  • 这条脚本结束时会自动执行:chown -R www:www /www/wwwroot/getDomain
hostname
systemctl status domaincheck-api --no-pager -l
systemctl status domaincheck-worker --no-pager -l
curl http://127.0.0.1:8100/health
curl http://127.0.0.1:8100/api/v1/runtime/preflight
curl http://127.0.0.1:8100/api/v1/runtime/readiness

判断标准:

  • health.status=ok
  • runtime/preflight.data.ok=true
  • 如果此时还没有接入大陆 controller / workerruntime/readiness.data.status=attention 是正常现象
  • 只有国外机自己的 PostgreSQL、Redis、API、systemd 报错时,才算国外主控机没部署好

2. 国内 controller 最短复制块

先把下面 3 个值替换掉再执行: 先把下面 5 个值替换掉再执行:

DB_NAME
DB_USER
DB_PASSWORD
REDIS_PASSWORD
SYNC_SHARED_TOKEN
MAINLAND_CONTROLLER_NODE_CODE
TARGET_API_BASE_URL

也可以直接改脚本头部变量后执行:

cp /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_controller_quick.conf.example \
   /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_controller_quick.conf

# 先编辑 install_mainland_controller_quick.conf
bash /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_controller_quick.sh

注意:

  • 这条脚本不会执行 git fetch
  • 这条脚本不会执行 git pull
  • 你要先自己把 /www/wwwroot/getDomain 更新到目标版本,再跑脚本
  • 这条脚本会自动过滤 Windows-only Python 依赖
  • 这条脚本结束时会自动执行:chown -R www:www /www/wwwroot/getDomain
hostname
systemctl status domaincheck-worker --no-pager -l
systemctl status domaincheck-sync-agent --no-pager -l
cd /opt/domaincheck/domain-api
bash deploy/multi-region/check_mainland_controller.sh

3. 国内 worker 最短复制块

先把下面 4 个值替换掉再执行: 先把下面 7 个值替换掉再执行:

DB_NAME
DB_USER
DB_PASSWORD
REDIS_PASSWORD
SYNC_SHARED_TOKEN
MAINLAND_WORKER_NODE_CODE
MAINLAND_CONTROLLER_IP
TARGET_API_BASE_URL

也可以直接改脚本头部变量后执行:

cp /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_worker_quick.conf.example \
   /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_worker_quick.conf

# 先编辑 install_mainland_worker_quick.conf
bash /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_worker_quick.sh

注意:

  • 这条脚本不会执行 git fetch
  • 这条脚本不会执行 git pull
  • 你要先自己把 /www/wwwroot/getDomain 更新到目标版本,再跑脚本
  • 这条脚本会自动过滤 Windows-only Python 依赖
  • 这条脚本结束时会自动执行:chown -R www:www /www/wwwroot/getDomain
hostname
systemctl status domaincheck-worker --no-pager -l

五、所有机器先执行一次

1. 安装基础环境

dnf update -y
dnf install -y epel-release
dnf install -y git nginx redis postgresql postgresql-server postgresql-contrib gcc gcc-c++ make wget curl tar policycoreutils-python-utils
dnf install -y python3.11 python3.11-devel

2. 克隆代码

mkdir -p /www/wwwroot
cd /www/wwwroot
git clone 你的仓库地址 getDomain
cd getDomain
git checkout main
git pull --ff-only origin main

3. 建立运行目录软链接

mkdir -p /opt/domaincheck
ln -sfn /www/wwwroot/getDomain/domain-api /opt/domaincheck/domain-api
ln -sfn /www/wwwroot/getDomain/domain-web /opt/domaincheck/domain-web
ln -sfn /www/wwwroot/getDomain/domainCheck /opt/domaincheck/domainCheck

4. 创建 Python 虚拟环境

cd /opt/domaincheck/domainCheck
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
python3.11 - <<'PY'
from pathlib import Path

source = Path("requirements.txt")
target = Path("requirements.linux.txt")
raw = source.read_bytes()
for encoding in ("utf-8", "utf-16", "utf-16-le", "utf-16-be", "gbk"):
    try:
        text = raw.decode(encoding)
        break
    except UnicodeDecodeError:
        continue
else:
    raise SystemExit("无法解析 requirements.txt 编码")

skip_prefixes = (
    "pywin32==",
    "pywin32-ctypes==",
    "twisted-iocpsupport==",
    "win32-setctime==",
)
lines = []
for line in text.splitlines():
    normalized = line.strip().lstrip("\ufeff")
    if normalized.lower().startswith(skip_prefixes):
        continue
    lines.append(normalized)

target.write_text("\n".join(lines) + "\n", encoding="utf-8")
PY
pip install -r requirements.linux.txt

cd /opt/domaincheck/domain-api
/opt/domaincheck/domainCheck/.venv/bin/pip install fastapi uvicorn pydantic-settings psycopg2-binary redis openpyxl python-multipart

六、国外机器一键部署

这一节默认你是:

  • 国外主控机
  • 可以使用宝塔管理 Nginx / PostgreSQL / Redis
  • 项目进程仍由 systemd 托管

国外机器承担:

  • domain-web
  • domain-api
  • PostgreSQL
  • Redis
  • domaincheck-worker

1. PostgreSQL 和 Redis 处理方式

如果你已经用宝塔装好了:

  • PostgreSQL
  • Redis

那这一步可以跳过,直接看后面的数据库账号和项目配置。

如果你不用宝塔,就执行下面命令。

2. 初始化 PostgreSQL

postgresql-setup --initdb
systemctl enable postgresql
systemctl start postgresql

创建数据库:

sudo -u postgres psql <<'SQL'
CREATE USER domainuser WITH PASSWORD '请改成你的强密码';
CREATE DATABASE domain OWNER domainuser;
GRANT ALL PRIVILEGES ON DATABASE domain TO domainuser;
SQL

3. 启动 Redis

systemctl enable redis
systemctl start redis

4. 配置 domainCheck/.env

cat >/opt/domaincheck/domainCheck/.env <<'EOF'
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=domain
DB_USER=domainuser
DB_PASSWORD=请改成你的强密码

REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
EOF

5. 初始化数据库结构

cd /opt/domaincheck/domainCheck
/opt/domaincheck/domainCheck/.venv/bin/python init_database.py

6. 配置前端生产环境

cat >/opt/domaincheck/domain-web/.env.production <<'EOF'
VITE_API_BASE_URL=https://api.domain.com/api/v1
EOF

7. 用 nvm 构建前端

如果这台机器还没装 nvm,先执行:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

nvm -v

然后固定使用:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 20
nvm use 20
node -v

然后再构建:

cd /opt/domaincheck/domain-web
npm install
npm run build

8. 配置 API 环境变量

cp /opt/domaincheck/domain-api/deploy/multi-region/templates/domaincheck-api.env.example /etc/default/domaincheck-api
sed -i 's#^DOMAIN_ROOT=.*#DOMAIN_ROOT=/opt/domaincheck/domainCheck#' /etc/default/domaincheck-api
sed -i 's#^API_HOST=.*#API_HOST=0.0.0.0#' /etc/default/domaincheck-api
sed -i 's#^API_PORT=.*#API_PORT=8100#' /etc/default/domaincheck-api
sed -i 's#^NODE_CODE=.*#NODE_CODE=overseas-control-01#' /etc/default/domaincheck-api
sed -i 's#^NODE_REGION=.*#NODE_REGION=overseas#' /etc/default/domaincheck-api
sed -i 's#^NODE_ROLE=.*#NODE_ROLE=control#' /etc/default/domaincheck-api
sed -i 's#^SYNC_PUSH_ENABLED=.*#SYNC_PUSH_ENABLED=false#' /etc/default/domaincheck-api
sed -i 's#^CORS_ORIGINS=.*#CORS_ORIGINS='\''["https://admin.domain","http://127.0.0.1:3201","http://localhost:3201"]'\''#' /etc/default/domaincheck-api

9. 安装 systemd

cp /opt/domaincheck/domain-api/deploy/systemd/domain-api.service /etc/systemd/system/domaincheck-api.service
cp /opt/domaincheck/domain-api/deploy/systemd/domain-worker.service /etc/systemd/system/domaincheck-worker.service

10. 修正权限

mkdir -p /opt/domaincheck/domain-api/runtime
touch /opt/domaincheck/domainCheck/detect_worker.log
chown -R www:www /opt/domaincheck/domain-api/runtime
chown www:www /opt/domaincheck/domainCheck/detect_worker.log
chmod 664 /opt/domaincheck/domainCheck/detect_worker.log
chown -R www:www /www/wwwroot/getDomain

11. 启动国外服务

systemctl daemon-reload
systemctl enable domaincheck-api
systemctl enable domaincheck-worker
systemctl restart domaincheck-api
systemctl restart domaincheck-worker

12. 配置 Nginx

如果你已经用宝塔建好了:

  • admin.domain
  • api.domain.com

并且已经在宝塔里配好了反代和静态站点,那么这一节可以不执行。

如果你不用宝塔,就直接执行下面命令。

后台站点:

cat >/etc/nginx/conf.d/admin.domain.conf <<'EOF'
server {
    listen 80;
    server_name admin.domain;

    root /opt/domaincheck/domain-web/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
EOF

API 站点:

cat >/etc/nginx/conf.d/api.domain.com.conf <<'EOF'
server {
    listen 80;
    server_name api.domain.com;

    location / {
        proxy_pass http://127.0.0.1:8100;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

启动 Nginx

nginx -t
systemctl enable nginx
systemctl restart nginx

13. 国外机器验收

curl http://127.0.0.1:8100/health
curl http://127.0.0.1:8100/api/v1/runtime/preflight
curl http://127.0.0.1:8100/api/v1/runtime/readiness

cd /opt/domaincheck/domain-api/deploy/linux
python3 smoke_test.py --base-url http://127.0.0.1:8100

结果解释:

  • runtime/preflight.data.ok=true 说明国外主控机自身部署已经通过
  • 如果此时 runtime/readiness.data.status=attention,而提示内容是“尚未观察到在线的大陆 controller / worker 节点”,这是正常现象
  • RedisBloom 出现降级告警不算阻塞项,只是性能优化项
  • 只有国外机自己的 PostgreSQL、Redis、systemd、DOMAIN_ROOT、API 启动失败时,才算国外主控机没收口

七、国内 controller 一键部署

这一节默认你是:

  • 国内 controller
  • 不装宝塔
  • 只跑 domaincheck-worker + domaincheck-sync-agent
  • 本机承载 Redis / PostgreSQL 控制面

1. 先准备 Redis 和 PostgreSQL

postgresql-setup --initdb
systemctl enable postgresql
systemctl start postgresql

systemctl enable redis
systemctl start redis

创建数据库:

sudo -u postgres psql <<'SQL'
CREATE USER domainuser WITH PASSWORD '请改成你的强密码';
CREATE DATABASE domain OWNER domainuser;
GRANT ALL PRIVILEGES ON DATABASE domain TO domainuser;
SQL

2. 配置 domainCheck/.env

cat >/opt/domaincheck/domainCheck/.env <<'EOF'
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=domain
DB_USER=domainuser
DB_PASSWORD=请改成你的强密码

REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
EOF

3. 执行 bootstrap

cd /opt/domaincheck/domain-api
bash deploy/multi-region/bootstrap_mainland.sh /opt/domaincheck controller

4. 配置 /etc/default/domaincheck-worker

cat >/etc/default/domaincheck-worker <<'EOF'
WORKER_MODE=linux-systemd
QT_QPA_PLATFORM=offscreen
NODE_CODE=mainland-controller-01
NODE_REGION=mainland
NODE_ROLE=control

DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=domain
DB_USER=domainuser
DB_PASSWORD=请改成你的强密码

REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0

SYNC_PUSH_ENABLED=true
SYNC_SOURCE_REGION=mainland
SYNC_TARGET_REGION=overseas
SYNC_TARGET_API_BASE_URL=https://api.domain.com/api/v1
SYNC_SHARED_TOKEN=请改成你的共享令牌
SYNC_BATCH_SIZE=200
SYNC_POLL_INTERVAL_SECONDS=30
EOF

5. 启动 controller 服务

systemctl daemon-reload
systemctl enable domaincheck-worker
systemctl enable domaincheck-sync-agent
systemctl restart domaincheck-worker
systemctl restart domaincheck-sync-agent

6. 本机检查

cd /opt/domaincheck/domain-api
bash deploy/multi-region/check_mainland_controller.sh

八、国内 worker 一键部署

这一节默认你是:

  • 国内纯 worker 节点
  • 不装宝塔
  • 不承载后台
  • 不承载 API
  • 不承载 Nginx

1. 配置 domainCheck/.env

如果它连接 controller 的同一套 Redis / PostgreSQL就改成 controller 地址:

cat >/opt/domaincheck/domainCheck/.env <<'EOF'
DB_HOST=国内controller机器IP
DB_PORT=5432
DB_DATABASE=domain
DB_USER=domainuser
DB_PASSWORD=请改成你的强密码

REDIS_HOST=国内controller机器IP
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
EOF

2. 执行 bootstrap

cd /opt/domaincheck/domain-api
bash deploy/multi-region/bootstrap_mainland.sh /opt/domaincheck worker

3. 配置 /etc/default/domaincheck-worker

cat >/etc/default/domaincheck-worker <<'EOF'
WORKER_MODE=linux-systemd
QT_QPA_PLATFORM=offscreen
NODE_CODE=mainland-worker-01
NODE_REGION=mainland
NODE_ROLE=worker

DB_HOST=国内controller机器IP
DB_PORT=5432
DB_DATABASE=domain
DB_USER=domainuser
DB_PASSWORD=请改成你的强密码

REDIS_HOST=国内controller机器IP
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0

SYNC_PUSH_ENABLED=true
SYNC_SOURCE_REGION=mainland
SYNC_TARGET_REGION=overseas
SYNC_TARGET_API_BASE_URL=https://api.domain.com/api/v1
SYNC_SHARED_TOKEN=请改成你的共享令牌
SYNC_BATCH_SIZE=200
SYNC_POLL_INTERVAL_SECONDS=30
EOF

4. 启动 worker

systemctl daemon-reload
systemctl enable domaincheck-worker
systemctl restart domaincheck-worker

九、统一更新命令

以后你更新代码,三台机器统一执行:

cd /www/wwwroot/getDomain
git fetch --all
git checkout main
git pull --ff-only origin main

然后:

国外机器

如果国外机器前端构建使用 nvm,更新时建议固定这么跑:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 20
nvm use 20

cd /opt/domaincheck/domain-web
npm install
npm run build

systemctl restart domaincheck-api
systemctl restart domaincheck-worker
systemctl restart nginx

如果国外机 Redis 只做本机运行态使用,并且当前 Redis 没有密码,记得保持:

sed -i 's#^REDIS_PASSWORD=.*#REDIS_PASSWORD=#' /opt/domaincheck/domainCheck/.env
systemctl restart domaincheck-api
systemctl restart domaincheck-worker

国内 controller

systemctl restart domaincheck-worker
systemctl restart domaincheck-sync-agent

国内 worker

systemctl restart domaincheck-worker

补充说明:

  • 一键部署脚本更新后,会在脚本末尾自动执行一次:
    • chown -R www:www /www/wwwroot/getDomain
  • 如果你是完全手工更新,也建议补执行一次,避免后续 www 用户 git pull 或宝塔读写再次撞权限

十、最终联调检查

在国外机器执行:

curl https://api.domain.com/api/v1/runtime/readiness
curl https://api.domain.com/api/v1/runtime/cluster
curl https://api.domain.com/api/v1/runtime/sync-summary

期望:

  • runtime/readiness.status 不是 blocking
  • runtime/cluster 能看到:
    • overseas-control-01
    • mainland-controller-01
    • mainland-worker-01
  • runtime/sync-summary 能看到 detect_result_batches

十一、如果当前还不能上国内机器

先在国外机器演练:

cd /opt/domaincheck/domain-api
bash deploy/multi-region/rehearse_multi_region.sh http://127.0.0.1:8100

如果它输出:

rehearsal passed

说明:

  • 多机脚本没问题
  • readiness 判断没问题
  • cluster 视图没问题
  • 可以开始把同样方式复制到其他机器

十二、最推荐的真实落地顺序

如果按你的使用习惯,我建议你就按下面走:

方案 A最符合你现在的习惯

  • 国外主控机:
    • 宝塔管理 Nginx / PostgreSQL / Redis / SSL
    • systemd 管理 domaincheck-api / domaincheck-worker
    • 前端构建使用 nvm
  • 国内 controller
    • 不装宝塔
    • PostgreSQL / Redis / domaincheck-worker / domaincheck-sync-agent
  • 国内 worker
    • 不装宝塔
    • 只跑 domaincheck-worker

方案 B如果以后你想进一步简化

  • 国外机继续保持不变
  • 国内 controller 也可以后续去掉本地 PostgreSQL只保留
    • Redis
    • domaincheck-worker
    • domaincheck-sync-agent
  • 国内 worker 全部连 controller 的 Redis 和数据库

当前阶段我建议你先不要改的

  • 不要为了统一而让国内 worker 也装宝塔
  • 不要为了“更标准”把 nvm 改成全局 Node
  • 不要让项目服务交给宝塔守护进程

十三、最终建议

你现在最稳的部署顺序就是:

  1. 先部署国外机器
  2. 国外机器 smoke test 通过
  3. 国外机器多机模拟演练通过
  4. 再部署国内 controller
  5. 再部署国内 worker
  6. 最后看 api.domain.com 的 readiness / cluster / sync-summary

一句话总结:

先把国外主控机跑稳,再用同样脚本扩到 2 台国内机器;代码更新统一走 git部署执行直接复制这份文档里的命令。