Skip to content

配套文件与源码

两份文档都有配套的可直接使用文件。这里提供在线浏览和打包下载两种方式。

原始 HTML 版本

这两份文档最初是以单文件 HTML 形式产出的:自包含、无外部依赖、可离线打开,版式也是照着 HTML 定制的。VitePress 版本方便在线查阅和检索,HTML 版本适合下载存档或转发。

两个版本的关系

内容一致。VitePress 版把长文档拆成了带侧边栏锚点导航的单页,并支持全文搜索与暗色模式;HTML 版保留了原始的彩色卡片式版式。看正文用 VitePress 版,存档转发用 HTML 版。

打包下载

两份文档的配套文件都打好了包,直接下载解压即可使用:

压缩包内容用途
argocd-files.zippatch-argocd.shproject-ruoyi.yamlapps-all.yamlargocd-server-ingress.yamlJenkinsfile.ci.gatewayclean.pyREADME.mdArgoCD 改造方案第 4~7 章要用到的清单与脚本
demo.zipserver/(长连接服务端 + Dockerfile)、client/(启动器)、manifest/(版本清单模板)、k8s/(Rollout 清单)、README.md客户端/服务端发布学习用的最小 demo

关于脚本的说明

argocd-files 里的脚本是改造方案的配套操作脚本(原文档第 4~7 章明确写出并解释过每条命令)。

demo刻意没有放任何构建/发布脚本——因为脚本会把过程藏起来,学习阶段需要逐条敲命令。demo 里的文件全是「被发布的软件本体」:server.js 是服务端程序、launcher.js 是客户端程序、Dockerfile 和 k8s 清单是它们的构建与部署定义。

目录结构

argocd-files

text
argocd-files/
├── README.md                      使用说明(含执行顺序与备份命令)
├── patch-argocd.sh                Argo CD 安装后的统一补丁:节点固定 / 拉取凭据 / 资源限额
├── project-ruoyi.yaml             AppProject:约束 Git 源、命名空间、资源类型
├── apps-all.yaml                  9 个 Application(config / 6 个后端 / gateway / ingress)
├── argocd-server-ingress.yaml     暴露 Argo CD Web UI(复用现有 nginx IngressClass)
├── Jenkinsfile.ci.gateway         改造后的 Jenkinsfile:仅 CI + 触发 CD
└── clean.py                       清洗从集群导出的 YAML,剥离运行时字段

demo

text
demo/
├── README.md                      操作手册:为什么这里没有脚本
├── server/
│   ├── server.js                  **服务端程序**:版本闸门 / 双协议 / 功能开关 / 分桶放量 / 摘流排空
│   ├── package.json               只依赖 ws
│   └── Dockerfile                 注意 CMD 必须用 exec 形式,否则收不到 SIGTERM
├── client/
│   ├── launcher.js                **客户端程序**:更新决策 / 差量补丁 / SHA256 校验 / 协议握手
│   └── package.json               零第三方依赖(内置极简 WebSocket 客户端)
├── manifest/
│   └── manifest.json              版本清单模板(含每个字段的说明)
└── k8s/
    └── rollout-canary.yaml        Argo Rollouts 金丝雀 + nginx 流量切分 + drain 配置

demo 里做进去的 9 个机制

server/server.js 不是「一个能跑的服务」,而是把这类项目最关键的机制都实现了一遍。读代码时可以对照文档第 1 章的术语:

代码位置对应概念文档章节
MIN_PROTOCOL / CURRENT_PROTOCOL协议兼容窗口1.4
握手检查 msg.protocol → 返回 reject版本闸门1.4
握手检查 msg.configVersion配置表版本校验1.8
FEATURE_FLAGS 环境变量Feature Flag(功能开关)1.3
bucketOf() 函数分桶 + 哈希雪崩混淆1.5
ROLLOUT_PERCENT放量百分比1.5
ready + /healthz 返回 503摘流(Drain)1.6
/livez 始终返回 200readiness 与 liveness 分离1.6
drain() 函数优雅停机 + 通知重连1.6

快速跑通 demo

bash
# 让 Node 可用(Node 装在 /root/node/bin)
export PATH=/root/node/bin:$PATH

# 1. 起服务端
cd demo/server
npm config set registry https://registry.npmmirror.com
npm install
FEATURES=new_map,new_shop SERVER_VERSION=1.2.0 node server.js

# 2. 另开终端,逐个验证四个机制
cd demo/client
node launcher.js --user 1001 --protocol 5     # 新客户端:通过 + 拿到功能
node launcher.js --user 1001 --protocol 4     # 老客户端:通过但功能为空 ← 最重要的一条
node launcher.js --user 1001 --protocol 3     # 太老:被版本闸门拒绝
node launcher.js --user 1001 --config cfg-x   # 配置表不一致:要求先热更
bash
# 3. 验证摘流 + 优雅排空
curl -s http://127.0.0.1:3000/healthz; echo              # 200
curl -s 'http://127.0.0.1:3000/drain?grace=3000'; echo   # 触发摘流
curl -s http://127.0.0.1:3000/healthz; echo              # 503 ← 摘流生效
curl -s http://127.0.0.1:3000/livez;  echo               # 200 ← 没被判定卡死

同时看客户端终端:应该收到 {"type":"reconnect", ...}而不是异常断开

Dockerfile 里的一个致命细节

dockerfile
CMD ["node", "server.js"]      # ✅ node 是 PID 1,能收到 SIGTERM
CMD node server.js             # ❌ /bin/sh 是 PID 1,会吞掉 SIGTERM

写成 shell 形式的话,K8s 发的 SIGTERM 会被 /bin/sh 吃掉,drain() 永远不会执行,Pod 到宽限期上限被 SIGKILL 硬杀,在线玩家全部异常掉线。这个细节决定了你的优雅停机是真的还是假的。

基于 VitePress 构建 · 内容为个人学习与工程实践笔记