六月初我们把 Xcode CI 和 OpenClaw Gateway 塞进同一台加拿大 M4,靠 launchd Nice=-5 和限制并发编译撑了两周。第三周起,业务同学开始在 IM 里抱怨「Gateway 又卡了」——构建日志显示一切正常,curl 健康检查却在高峰期从 50ms 漂到 400ms 以上。调了并发、清了 DerivedData、甚至临时升了 24GB 套餐,问题只是从「每天两次」变成「每天一次」。
这不是配置写错,而是同机资源模型到了天花板。端口不冲突(20300 vs 18789),CPU 核数也够,真正打架的是统一内存与 swap。本文接 同机部署与 launchd 调优 之后的路径:什么时候必须拆成双节点、拓扑怎么画、迁移怎么切流而不炸 Channels。官方内存与进程行为可参考 Apple 的 Xcode 构建缓存文档;Tailscale 组网见 Tailscale 安装指南。
结论先行:分水岭在资源隔离,不在「再买一台机器」。
-
四条硬信号,满足任一即拆
构建 ≥50 次/天、并发 ≥3 路、Gateway 面向终端用户、或 swap 周内 ≥3 次 Critical——继续同机调 Nice 只是拖延。
≥50 次/天
-
最小双节点:构建机 + Gateway 专机
构建节点保留 24GB+ 与大盘;Gateway 节点 16GB 足够常驻 ~500MB。两台 M4 经 Tailscale 内网互联,公网只暴露必要入口。
16GB Gateway 专机
-
迁移核心:状态与 DNS,不是重装
rsync 配置目录、复用 token、Tailscale 魔术 DNS 切流;构建机不停机,Gateway 蓝绿切换窗口控制在 15 分钟内。
蓝绿 ≤15 min
1. 为什么同机方案会「突然不够用」
很多团队的第一台云 Mac 同时承担三件事:跑 xcodebuild、挂 OpenClaw Gateway 18789、偶尔 VNC 上去点钥匙串。初期负载低,16GB 看起来绰绰有余。随着分支增多、UI 测试并行、Channels 从内部试跑变成对外服务,内存曲线从「锯齿」变成「平台」——构建结束后的 10 分钟里,compressed 页面仍占 8GB 以上,Gateway 的 heap 继续被挤进 swap。
同机调优(降并发、提 Nice、清缓存)解决的是峰值重叠概率,不能消灭峰值本身。当两个高峰在时间轴上几乎必然重叠——例如亚太白天构建、北美晚间 IM 高峰——你就不是在优化参数,而是在赌调度器。Apple Silicon 的统一内存没有独立显存缓冲,Xcode 与 Node.js Gateway 争的是同一块物理池;memory_pressure 进入 Warn 后,延迟抖动对用户是可感知的,对 CI 则是偶发超时与签名步骤失败。
拆机的本质不是「扩容神话」,而是把不可压缩的峰值拆开:让构建峰值只打在构建节点,让 Gateway 常驻内存永远不被 xcsbuildd 挤占。这与 GitHub Actions 自建 macOS Runner 上云 Mac 里「专用 Runner 不混桌面」是同一逻辑,只是这里拆的是 Gateway 与 CI。
2. 三种拓扑分类:同机、双节点、三节点
先归类再选型,避免一上来就「加两台」:
- T0 同机共存:一台 M4 同时跑 Xcode Server / 自建 Runner + Gateway。适合日构建 <30 次、Gateway 仅内部、可接受偶发延迟。
- T1 双节点(本文主角):节点 A 专职 CI(24GB+、大 SSD);节点 B 专职 Gateway(16GB 即可)。Tailscale 或机房内网互通,Channels 与 Dashboard 指向 B,构建触发走 A。
- T2 三节点:在 T1 上再拆「签名/上传专机」或「并行测试专机」。当日构建 >150 次、或 TestFlight 上传与编译必须硬隔离时再考虑;否则 T1 足够多数中小团队。
非对称结论再说一次:问题不在 M4 性能不够,而在你把两种 SLA 不同的服务绑在同一内存池里。 Gateway 要 99.9% 平稳响应;CI 要吞吐。同机是在用一套 SLA 妥协两个目标。
3. 同机 vs 双节点 vs 升配:怎么比
| 维度 | 继续同机调优 Nice / 降并发 | 单机升 32GB 加内存不换拓扑 | 拆成双节点 CI + Gateway 分机 |
|---|---|---|---|
| 解决根因 | 缓解峰值重叠 | 抬高内存天花板 | 隔离两种 SLA |
| Gateway 延迟 | 仍随构建抖动 | 改善但非消除 | 构建期可保持 <100ms |
| 月成本(粗算) | 最低 | 中(升配差价) | 中(+16GB 小机) |
| 运维复杂度 | 低 | 低 | 中(多一台、Tailscale) |
| 适合阶段 | 日构建 <30 | 并发 2 路、内部 Gateway | ≥50 次/天或对外 Gateway |
| 信号 | 阈值 | 观测方式 | 误报排除 |
|---|---|---|---|
| 构建频率 | ≥50 次/天 | CI 日志 / Runner 计数 | 排除手动本地 Archive |
| 并发路数 | ≥3 路全量构建 | xcodebuild -jobs 与队列深度 | 轻量 lint 不算一路 |
| Gateway 受众 | 终端用户 / 7×24 Channels | 产品侧 SLA 要求 | 纯内部 webhook 可暂缓 |
| 内存压力 | 周内 ≥3 次 Critical | memory_pressure 日志 | 一次性泄漏需先排查 |
| 磁盘争用 | 月产物 >50GB 且 I/O wait 高 | df -h + iostat | 先清 archive 再判断 |
4. 场景怎么选:决策矩阵
- 两人团队、日构建 <20、Gateway 仅自用:留在 T0,做好 同机 launchd 调优 即可。
- 亚太触发构建、Gateway 服务 IM 用户:直接 T1。Follow-the-sun 下高峰几乎必重叠,同机必输。
- 已有 GitHub Actions 云 Runner,Gateway 刚上线:Runner 在 A,Gateway 放 B;不要在 Runner 机上再挂 18789。
- TestFlight 上传与编译抢磁盘:先 T1;仍不够再 T2 加签名/upload 专机,参考站内 TestFlight 专文,勿与本文混为一谈。
- 预算只够一台机:优先保证 Gateway SLA,构建改夜间批跑或降并发——这是妥协,不是长期架构。
5. 推荐组合(可叠加)
- 最小双节点栈:Hashvps 加拿大 M4 24GB(A,CI)+ M4 16GB(B,Gateway)+ Tailscale tailnet +
openclaw doctor周检。适合从 T0 升级的大多数团队。 - CI 混合栈:A 机自建 Runner 接 GitHub Actions;B 机 Gateway + Channels。编排层在 GitHub,执行面在 macOS,Gateway 不背构建峰值。与 2027 macOS 构建市场变迁 里的「环境主权」方向一致。
- 可观测栈:在 B 机常驻 Gateway 延迟探针(
curl5s 间隔)+ A 机构建结束 hook 写memory_pressure快照;两周数据足以向管理层证明拆机 ROI。
6. 迁移前常见误区
- 先停机构建再迁 Gateway:构建停机成本高;应 Gateway 蓝绿、构建不停。
- 新机器重装而不 rsync 状态:
~/.openclaw、token、Channels 配对状态丢失会导致全员重登。 - 公网双 IP 同时暴露 18789:切流期应用 Tailscale 或内网 DNS,避免两个 Gateway 同时接 Channels。
- 构建机删 Gateway 目录太早:回滚窗口内保留旧机 Gateway 进程,仅改 DNS 指向。
- 忽视时钟与证书:两台机 NTP 偏差 >30s 会导致 token 校验偶发失败;迁移日先
sudo sntp -sS time.apple.com。
7. 落地步骤:7 步完成双节点迁移
以下 Runbook 假设:原机 mac-ci-01 同机运行 CI+Gateway;新购 mac-gw-02(16GB)专跑 Gateway。Tailscale 已安装(详见 OpenClaw 日常运维 Runbook)。
第 1 步:基线快照(迁移日前一天)
在原机记录 Gateway 延迟 P50/P95、构建次数、memory_pressure 分布,作为拆机后对比。导出 openclaw status 与 Channels 列表截图。
# 延迟采样 60 次
for i in $(seq 1 60); do
curl -o /dev/null -s -w "%{time_total}\n" http://127.0.0.1:18789/health
sleep 5
done | sort -n | awk '{a[NR]=$1} END{print "p50="a[int(NR*0.5)],"p95="a[int(NR*0.95)]}'
memory_pressure
vm_stat | head -8
第 2 步:新机初始化与 Tailscale 入网
在 mac-gw-02 完成 macOS 更新、安装 Homebrew、Node、Tailscale;确保与 mac-ci-01 互 ping <5ms。不要在新机跑任何 xcodebuild。
第 3 步:rsync Gateway 状态(维护窗口开始)
# 在原机 mac-ci-01 执行;先停 Gateway 避免写入分裂 sudo launchctl unload /Library/LaunchDaemons/com.openclaw.gateway.plist rsync -avz --delete \ ~/.openclaw/ \ builder@mac-gw-02.tailnet-abc.ts.net:~/.openclaw/ # 同步 launchd plist scp /Library/LaunchDaemons/com.openclaw.gateway.plist \ builder@mac-gw-02.tailnet-abc.ts.net:/tmp/
第 4 步:新机启动 Gateway 并本机验收
sudo cp /tmp/com.openclaw.gateway.plist /Library/LaunchDaemons/ sudo launchctl load /Library/LaunchDaemons/com.openclaw.gateway.plist openclaw doctor curl -s http://127.0.0.1:18789/health sudo lsof -iTCP:18789 -sTCP:LISTEN
第 5 步:切流——Tailscale 魔术 DNS 或反向代理
将团队使用的 Gateway 主机名(如 gateway.tailnet-abc.ts.net)解析到新机;移动端与 Channels 配置改指向新 MagicDNS 名称。切流期间不要在原机重启 Gateway。
第 6 步:构建机减负
确认 Channels 与 Dashboard 在新机正常后,在原机卸载 Gateway launchd,释放内存给 CI。可将并发编译任务数调回 5–6(24GB 机)。
# mac-ci-01:确认已无流量打到 18789 后
sudo launchctl unload /Library/LaunchDaemons/com.openclaw.gateway.plist
sudo mv /Library/LaunchDaemons/com.openclaw.gateway.plist \
/Library/LaunchDaemons/com.openclaw.gateway.plist.bak
defaults write com.apple.dt.Xcode \
IDEBuildOperationMaxNumberOfConcurrentCompileTasks 6
第 7 步:观察 48 小时与回滚预案
保留原机 .openclaw 备份与 plist.bak 七天。若新机 Gateway P95 >200ms 或 Channels 掉线,将 DNS 指回原机并 launchctl load 旧 plist——全程无需动 CI 队列。新网关安装细节可对照 OpenClaw 远程 Mac 安装部署。
8. FAQ
Q1. 只有 16GB 一台机,能不能先拆「逻辑角色」而不买第二台?
不能代替物理拆机。 你可以用时间段错开(夜间构建、白天 Gateway),但 Follow-the-sun 或 7×24 Channels 下迟早再撞峰值。逻辑拆分的唯一价值是验证「迁走 Gateway 后延迟是否恢复」,用于向采购证明第二台的必要性。
Q2. 双节点必须用 Tailscale 吗?
不必须,但强烈推荐。 同一云厂商内网、WireGuard 自建、或 SSH 隧道均可;Tailscale 的优势是 MagicDNS、ACL 与低运维。两台 Hashvps 加拿大 M4 在同区域时,内网 RTT 通常 <2ms,足够 Gateway 调 A 机上的构建 webhook。
Q3. 双节点比单机 32GB 贵多少?
取决于套餐,但常接近「24GB 构建机 + 16GB 小机」vs「单机 32GB」。 关键不在绝对差价,而在 Gateway SLA 是否可证明:对外服务团队应用停机时间算账,而非只看月租。
Q4. GitHub Actions 托管 Runner 还要自建 Mac 吗?
看环境主权。 托管 macOS 按分钟计费,适合波峰;自建云 Mac 适合固定日构建量 >50 且要控密钥与 DerivedData。Gateway 仍建议独立节点,与 Runner 托管与否无关。
Q5. 迁移失败最快回滚怎么做?
DNS 指回 + 原机 launchctl load。 不要在回滚日跑大规模构建;先验证 Gateway health 与一条 Channel 消息,再放开 CI。状态目录保留双份直至新业务指标稳定。
9. 总结
Mac M4 CI 拆机不是失败,而是同机调优成功后的自然下一阶段:你已经证明业务需要同时跑构建与 Gateway,只是物理上不该再挤一张内存条。记住四条硬信号、用 T1 双节点隔离 SLA、用 7 步 Runbook 做蓝绿切换——分水岭在资源隔离,不在机器数量。
若你正卡在「Gateway 又卡了但构建不能停」的窗口,优先加一台 16GB Gateway 专机,比继续调 Nice 更接近根治。构建继续跑在 24GB 云上,Agent 与用户在另一台机器上获得稳定 18789——这才是 2026 年小团队能负担的「准生产」拓扑。
双节点拆机,从两台云 Mac mini 开始
Xcode CI 与 OpenClaw Gateway 分机后,构建机需要 24GB 与大 SSD 扛 DerivedData,Gateway 机 16GB 即可 7×24 低延迟在线。Hashvps 加拿大 M4 裸金属、独享 IPv4、SSH/VNC 开箱即用,两台机器同区域组网延迟低,适合作为 T1 双节点的起步配置——比单机硬升 32GB 更能隔离 swap 抖动。
若你正在规划从同机迁到双节点, Hashvps 云端 Mac mini M4 是性价比较高的第二台起点—— 立即了解套餐方案 ,让 Gateway 与 CI 各得其所。