优化: - initArtalk 加节点级幂等守卫(mount.__atkInited,失败回滚), 消除 artalk.html/mypjax 多入口导致的 4× comments + 4× pv 重复请求 - fetch 包装层对无 body 的 GET/HEAD 去掉多余 content-type, 消掉 Artalk 对 GET /comments 的 CORS 预检(按完整 URL 缓存, 每篇文章都重付一次 RTT)。实测评论列表 +1150~1565ms → +626ms 修复: - 评论列表骨架屏改注入 .atk-list-body(原骨架在 #Comments 内, 被 Artalk.init 清空),list-loaded/故障/12s 兜底移除 - 友链申请弹窗抽成 modules/friendlink.js 进 page-only bundle (原内联脚本在 #pjax-container 外,pjax 后 flApplyOpenModal 未定义) - toast 统一走本地化 Message.js/Qmsg 适配层(保留 window.Toast/showToast 旧 API) 文档: - README / 架构总览 更新;新增 评论加载优化方案.md
166 lines
8.2 KiB
Markdown
166 lines
8.2 KiB
Markdown
# 优世界博客 · 架构总览
|
||
|
||
> 更新时间:2026-10-04(CNB 迁移完成当日)
|
||
> 状态:**迁移已落地并跑通**(四线路全绿,单次发布约 3.5 分钟)
|
||
> 本文档只描述**现状**;迁移前的复杂度审计与选型过程见文末「相关文档」。
|
||
|
||
---
|
||
|
||
## 0. 一句话
|
||
|
||
四个子系统,一条 **3 步**的托管发布链路。构建与发布已从「自建 Gitea + act_runner + 广州中转机」迁到
|
||
**腾讯云 CNB(cnb.cool)** —— **需要自己运维的机器从 3 台降到 0 台**。
|
||
|
||
---
|
||
|
||
## 1. 全景
|
||
|
||
### 1.1 四个子系统
|
||
|
||
| # | 子系统 | 技术栈 | 跑在哪 | 状态 |
|
||
|---|---|---|---|---|
|
||
| **1** | **内容系统** | Hugo 0.128.2 extended + Ying 主题,138 篇 md;产物约 3200 文件 / 424MB | 产物分发到 3 个 CDN | 正常 |
|
||
| **2** | **评论系统** | `blog-admin/` = artalk-cf(Artalk v2 兼容服务端)+ RSS 机器人 | Cloudflare Workers + D1 + KV → `api.200181.xyz` | ✅ 零服务器零运维 |
|
||
| **3** | **写作系统** | `write-server/`(Next.js 16,`post.usj.cc`)<br>`write/`(本地 Windows 前端) | 独立 Docker 主机/本机 | 可用(两套前端功能重叠) |
|
||
| **4** | **发布基础设施** | **CNB 流水线**(`.cnb.yml`)+ 又拍云 + 多吉云 + EdgeOne | 腾讯云 CNB(**托管**) | **新建,已跑通** |
|
||
|
||
### 1.2 服务与地址地图
|
||
|
||
| 角色 | 地址 / 位置 | 说明 |
|
||
|---|---|---|
|
||
| **代码主仓** | `cnb.cool/zqlit/blog` | CNB,**私有**;构建由它触发 |
|
||
| **代码备份** | `github.com/zqlit/blog` | 仅作备份,**不参与构建** |
|
||
| **构建 + 发布** | CNB 流水线(腾讯云国内节点,4 核 8G) | 托管,0 元(免费额度内) |
|
||
| **密钥仓库** | `cnb.cool/zqlit/blog-secrets` | CNB「密钥仓库」类型,10 项变量经 `imports` 注入 |
|
||
| **境内源站** | 又拍云对象存储 | 由 CNB 国内节点**直传**(原为 `if: false` 的死代码) |
|
||
| **国内加速** | 多吉云 CDN | 回源又拍云 |
|
||
| **境外线路** | EdgeOne Pages(项目 `hugo-blog`,`--area overseas`) | 腾讯 EdgeOne 国际站 |
|
||
| **评论后端** | `api.200181.xyz` | Cloudflare Workers |
|
||
| **通知** | QQ 邮件(`imql@qq.com`) | 已收敛为**单一通道** |
|
||
|
||
> 关键点:境内、境外仍是**两条独立线路**,但**由同一条流水线一次推完** ——
|
||
> 这是本次迁移最大的结构性改善。
|
||
|
||
---
|
||
|
||
## 2. 一次发布的完整旅程(3 步)
|
||
|
||
```
|
||
① 写作 write-server(网页) 或 write/(本地 Windows)
|
||
│
|
||
② git push git pushall = git push origin main ; git push gh main
|
||
│ ├─ origin → cnb.cool/zqlit/blog (主仓,触发构建)
|
||
│ └─ gh → github.com/zqlit/blog (备份,不构建)
|
||
▼
|
||
③ CNB 流水线(国内节点,约 3.5 分钟,7 个 stage 顺序执行)
|
||
├─ 1. Hugo 构建 草稿隐藏预处理 → hugo --minify --gc → 算构建哈希
|
||
├─ 2. 同步到又拍云 upx sync(境内直传,非阻断但如实上报)
|
||
├─ 3. 刷新又拍云 CDN purge 首页 + sitemap/rss/archives/posts 等固定入口
|
||
├─ 4. 刷新多吉云 CDN node scripts/refresh_cdn.js
|
||
├─ 5. 部署 EdgeOne edgeone pages deploy --area overseas
|
||
├─ 6. 上报部署状态 POST api.200181.xyz/api/deploy-status
|
||
└─ 7. 邮件通知 成功 → stages 末尾;失败 → failStages
|
||
```
|
||
|
||
**对照**:迁移前是 **7 步,中间有 3 个环节是你自己运维的服务器**。
|
||
|
||
---
|
||
|
||
## 3. 流水线细节(`.cnb.yml`,284 行)
|
||
|
||
| 触发 | 条件 | 说明 |
|
||
|---|---|---|
|
||
| push | 推送到 `main` | 主链路 |
|
||
| crontab | `0 9 * * *`(Asia/Shanghai) | 每天 09:00,与 push **共用同一组 stage**(YAML 锚点) |
|
||
|
||
| 机制 | 实现 |
|
||
|---|---|
|
||
| 构建镜像 | `deploy/Dockerfile`,hugo 二进制**随仓库携带**(`bin/linux/hugo`,linux/amd64) |
|
||
| ⚠️ docker 上下文 | `by: [bin/linux/hugo]` —— CNB 的 docker build **只看得见 Dockerfile + by 列出的文件**,漏写会报 `not found` |
|
||
| 密钥注入 | `imports: https://cnb.cool/zqlit/blog-secrets/-/blob/main/secrets.yml` |
|
||
| stage 间传状态 | 落盘 `.ci_status`(原版靠 `needs.*.outputs`) |
|
||
| 并发控制 | `lock.cancel-in-progress`(对应原 `concurrency`) |
|
||
| 非阻断 | 又拍云三步 + 状态上报 + 邮件用 `allowFailure: true`,失败仍写状态如实上报 |
|
||
| 资源 | `cpus: 4`(4 核 8G) |
|
||
|
||
---
|
||
|
||
## 4. 迁移前后对比
|
||
|
||
| 维度 | 迁移前(Gitea 自建) | 迁移后(CNB) |
|
||
|---|---|---|
|
||
| 发布链路环节 | **7 步** | **3 步** |
|
||
| 自维护机器 / 服务 | **3 台**(Gitea 主机 + act_runner + 广州中转机) | **0**(构建托管) |
|
||
| 流水线定义 | GitHub Actions **1169 行** | `.cnb.yml` **284 行** |
|
||
| 产物传递 | 打 `tar.zst` → artifact → 中转机跨境下载 | 同一 pipeline **共享工作目录**,无需传递 |
|
||
| 又拍云直传 | `if: false`(境外 runner 必挂,**从未跑通**) | **已跑通**(国内节点直传) |
|
||
| COS 中转层 | 需要(存储 + 流量账单) | **已砍** |
|
||
| `github.server_url` 兼容分支 | **8 处** | **0** |
|
||
| 通知 | 3 套(TG / 飞书 / 邮件),约 400 行 | **1 套**(邮件) |
|
||
| 图片优化 + 反向 commit | CI 内每轮白跑(15 张老图处理不掉) | **未迁**(如需保留,照搬 `scripts/optimize_images.js`) |
|
||
| 构建环境 | 境外 VPS | 腾讯云**国内节点** 4 核 8G |
|
||
| 费用 | VPS 月租 | **0 元**(100GiB 仓库 + 160 核时/月) |
|
||
| 单次发布耗时 | — | **约 3.5 分钟** |
|
||
|
||
> 原链路里那些补丁(COS 中转 / `sync.sh` 每分钟轮询 / artifact 打包 / 兼容分支)
|
||
> **唯一根因是「runner 在境外」**。CNB 节点在国内,这一整层随之消失。
|
||
|
||
---
|
||
|
||
## 5. 运维要点
|
||
|
||
### 5.1 推送
|
||
|
||
```bash
|
||
git pushall # 别名 = git push origin main; git push gh main
|
||
```
|
||
|
||
用 `;` 而非 `&&` —— **一段失败不影响另一段**(实测:串联 `pushurl` 时第一个失败会中止后续)。
|
||
|
||
### 5.2 远端
|
||
|
||
| remote | 地址 | 角色 |
|
||
|---|---|---|
|
||
| `origin` | `https://cnb.cool/zqlit/blog.git` | **主仓**(fetch + push) |
|
||
| `gh` | `git@github.com:zqlit/blog.git` | **备份**(push) |
|
||
| `gitea` | 自建 `23.254.236.47:3001` | 过渡期只读参考,稳定后手工删 |
|
||
|
||
### 5.3 凭据
|
||
|
||
- 令牌存**仓库外**:`~/.workbuddy/secrets/cnb-token`
|
||
- 本仓 `credential.helper` 指向一个自定义脚本;`.git/config` **无明文**
|
||
- ⚠️ 本机全局 helper 是 **GCM**(会弹窗、对第三方 HTTPS 远端还会挂死);wincred 对 cnb.cool 有过「幽灵记录」删不掉 → 故用自定义 helper 绕开
|
||
|
||
### 5.4 密钥
|
||
|
||
- 修改密钥 → 编辑 CNB 密钥仓库的 `secrets.yml`(**网页编辑,禁 clone**)
|
||
- 本地 `cnb-secrets.yml` 只是粘贴草稿(已 gitignore,**不入库**)
|
||
- ⚠️ CNB 的 `imports` 是**一层映射**(key 就是变量名本身);又拍云服务名在 CNB 里必须叫
|
||
**`UPYUN_SERVICE`**(旧 Gitea 里叫 `UPYUN_BUCKET`,照抄会「变量未定义」)
|
||
|
||
---
|
||
|
||
## 6. 遗留待办
|
||
|
||
| # | 项 | 说明 |
|
||
|---|---|---|
|
||
| 1 | `gitea` remote | 只读保留,稳定几天后 `git remote remove gitea` |
|
||
| 2 | GitHub 侧旧 workflow | `deploy.yml` / `cleanup.yml` / `aliyun-backup.yml` 已无用途,可删 |
|
||
| 3 | 令牌 scope | 缺 `repo-cnb-history:r`(读构建日志);补上后 agent 可自行排错 |
|
||
| 4 | Gitea 主机 | 发布链路已不依赖;是否退役取决于其它用途 |
|
||
| 5 | 广州中转机 | 同上(`sync.sh` 轮询已无用;机上另有 1Panel / vaultwarden 等服务) |
|
||
| 6 | `README.md` | 仍写着旧 GitHub Actions 流程,待更新 |
|
||
|
||
---
|
||
|
||
## 附:相关文档
|
||
|
||
- `CNB构建落地方案.md` — 迁移实施方案与实测数据
|
||
- `代码源与构建平台选型.md` — 平台对比(CNB / Gitee / GitLab / EdgeOne / 阿里云 ESA)
|
||
- `砍COS改造步骤.md` — COS 下线记录
|
||
- `EdgeOne双区域方案评估.md`、`Gitee方案评估.md`、`阿里云ESA评估.md`、`精简方案-只留CF和Hugo.md` — 决策期评估
|
||
|
||
**证据出处(现行)**:`.cnb.yml`(284 行)、`deploy/Dockerfile`、`bin/linux/hugo`、
|
||
`scripts/send_mail.js`、`scripts/refresh_cdn.js`、`scripts/setup-cnb-remotes.sh`。
|
||
已退役参考:`.github/workflows/deploy.yml`(1169 行)。
|