ADR-0006 展示環境的成本上限是零,代價是冷啟動
已採納 · 2026-09-10
這一篇和其他幾篇不同:它不是來自我在前一份工作踩過的坑,而是這個專案自己的托管決定。 按照本站的規則,這點要先講明,免得讀起來像借來的經驗。
api.weihsin.dev 是求職用的展示服務,不是營運中的系統。它的實際條件是:
- 流量零星。讀者是招募方與面試官,一天可能是個位數的請求,也可能整週沒有。
- 沒有可用性承諾。沒人靠它做事,掛掉幾分鐘不會有任何後果。
- 必須有 HTTPS。
.dev在 HSTS preload 名單裡,瀏覽器只走 HTTPS,沒有 http 退路。 托管平台必須提供憑證,這不是選配。 - 成本上限是零。這是我給自己設的硬條件,理由見下。
部署到 Azure Container Apps,並且:
| 項目 | 設定 | 月成本 |
|---|---|---|
| 副本數 | minReplicas=0 |
零副本不計費,合計 $0 |
| 映像倉庫 | ghcr.io 公開映像 |
$0 |
| 日誌 | --logs-destination none |
$0 |
| 自訂網域憑證 | 平台的 managed certificate | $0 |
Consumption 方案每月每訂閱有 180,000 vCPU-秒、360,000 GiB-秒、200 萬次請求的免費額度, 而縮到零時連這些都不會消耗。
免費不是為了省那幾塊美金,是為了讓這個服務可以一直開著。
一個求職作品最糟的結局,是三個月後因為忘記關而產生帳單,於是把它關掉—— 然後履歷上的連結變成死的。每月零元的服務沒有被關掉的理由,它可以在那裡放很多年。 這是選擇零成本真正的原因,不是預算。
三筆錢分別是這樣消掉的:
- Azure Container Registry 沒有免費層,Basic 每天 $0.1666(約每月 $5)。
換成
ghcr.io的公開映像。GitHub 的套件可見性與原始碼 repo 的可見性是分開設定的, 所以映像公開不代表原始碼必須公開。 - 日誌落地按 GB 計費,而且沒有免費額度。關掉儲存後仍可看即時的 log stream, 失去的只是事後用查詢語言翻歷史。對一個記憶體狀態、每小時重置的服務,這不值得付費。
- 常駐副本要錢。以最小配置 0.25 vCPU / 0.5 GiB 估算,扣掉免費額度後約每月 $4.21。 縮到零就是 $0。
首次請求要等冷啟動。 沒有流量時容器是關的,下一個請求會觸發啟動,要等數秒。 點進來的人第一眼看到的是等待。這是這個決定最直接、也最痛的代價—— 而且付出代價的正好是我希望留下好印象的那個人。
記憶體狀態的存續期比原本設計的更短。 這一點是 ADR-0001(不接資料庫)和本篇的交互作用,值得單獨講:
服務原本的設計是資料放記憶體、每小時重置。但縮到零之後,真正決定資料何時消失的 不再是那個一小時的計時器,而是有沒有人在用。沒人用十分鐘,容器關掉,狀態就沒了。
所以「每小時重置」實際上變成了「重置間隔 ≤ 一小時,且不可預期」。 對一個沙箱來說這無所謂——重置本來就是預期行為。但如果有人想連續操作、 中間停下來讀個文件再回來,他可能會發現剛才建立的案件不見了。 這是使用者真的會遇到的行為,不是理論上的風險。
沒有歷史日誌可查。 線上出問題時只能重現,不能回溯。 如果這是營運服務,這個取捨完全不成立。
綁在特定平台的免費額度上。 免費額度是廠商的商業決定,可以改。 真的改了就得搬家,而搬家成本就是這裡省下的錢的真正價格。 容器化本身讓搬家不至於太痛,但 DNS、憑證、自訂網域的設定都要重來。
考慮過的替代方案
Section titled “考慮過的替代方案”常駐一個最小副本(約 $4.21/月)。 這確實能消掉冷啟動。 沒有選它是因為前面說的理由:會產生帳單的東西,終究有一天會被關掉。 如果之後真的有穩定流量,這個決定應該被重新檢視——那時代價的天平是反過來的。
定時 ping 保溫。 每幾分鐘打一次 /health 讓容器不要關。
這個方案是自欺。 保溫成功就表示副本幾乎全時在跑,於是回到常駐的成本,
只是換了個名目、還多了一個要維護的排程。省錢和熱機不能同時要,選一個。
其他雲平台。 Google Cloud Run 的免費額度與此幾乎相同,也能縮到零、也給免費憑證。 沒有選它的理由與技術無關:成本同樣是零,而換平台要回頭改已經寫完的文件。 兩個零之間不需要比較。