六月初我們把 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+ 與大容量 SSD;Gateway 節點 16GB 足夠常駐 ~500MB。兩台 M4 經 Tailscale 內網互聯,公網只暴露必要入口。
16GB Gateway 專機
-
遷移核心:狀態與 DNS,不是重裝
rsync 設定目錄、複用 token、Tailscale MagicDNS 切流;建置機不停機,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 MagicDNS 或反向代理
將團隊使用的 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 各得其所。