跳至主要內容
ACE 服務實戰 — 第 7/11 篇

App Engine 怎麼部署和切流量?先選 Standard 或 Flexible

內文字級

App Engine 怎麼部署和切流量?先選 Standard 或 Flexible
更新:2026-10-07

前言

想部署應用,但不打算自己維護 VM 或容器叢集,App Engine 是可評估的平台。它會管理底層執行環境,不過 Standard 與 Flexible 的限制、擴縮方式和費用不同,不能只看「都能部署程式」就當成一樣。

這篇先比較兩種執行環境,再看 app.yaml 怎麼定義服務、如何保留版本並分配流量。最後把 App Engine 放回 Cloud Run 和 Cloud Run functions(原 Cloud Functions)的選型裡。

App Engine 版本與流量管理:Source 與 app.yaml 部署到 Service 後建立互相獨立且 immutable 的 Version v1、Version v2,各自 Automatic scaling;Traffic router 先以 90%/10% canary 分流,Errors and latency 健康時只調整流量逐步 Promote v2,異常時立即 Rollback to v1,不需重新建置;Standard 為 sandboxed runtimes 且依 scaling mode 可能縮至零,Flexible 執行於 Compute Engine VM、至少一個 instance 且啟動較慢

每次部署會建立新的 immutable version;canary、promote 與 rollback 都只是調整 traffic split,不是原地覆寫或重新 build。兩個版本各自擴縮、監控錯誤率與延遲。底部再把環境差異收斂:Standard 是否縮至零仍取決於 scaling mode,Flexible 跑在 VM 上且至少維持一個 instance。


Standard vs Flexible

App Engine 有兩個環境,兩者差很多。先記一個會反覆出現的詞:scale-to-zero(縮容至零)=沒人用的時候實例數降到 0,完全不收錢。

特性StandardFlexible
底層Google 沙盒(gVisor)Compute Engine VM
語言指定 runtime(Python、Java、Go、Node.js、PHP、Ruby)任何語言(Docker 容器)
縮容至零✅ 可以❌ 最少 1 個實例
啟動速度秒級分鐘級(啟動 VM)
檔案系統唯讀(只有 /tmp 可寫)可寫(但重啟會消失)
WebSocket❌ 不支援✅ 支援
VPC 存取VPC Connector(或 Direct VPC egress,Preview)原生 VPC
SSH 連入❌✅ 可以 SSH
免費層✅ 28 F-hours/天❌ 無免費層

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

怎麼選?

實務上九成情況一句話就能決定——沒有容器或長連線的硬需求,就 Standard:

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START{"應用需要自訂 Runtime、OS 套件<br/>Docker 映像或 SSH 嗎?"}
  START -->|"是"| FLEX["App Engine Flexible"]
  START -->|"否"| SOCKET{"需要 WebSocket<br/>或長連線嗎?"}
  SOCKET -->|"是"| FLEXOR["優先評估 Cloud Run<br/>或使用 Flexible"]
  SOCKET -->|"否"| ZERO{"重視快速啟動、免費層<br/>或 scale-to-zero 嗎?"}
  ZERO -->|"是"| STANDARD["App Engine Standard"]
  ZERO -->|"否"| SIMPLE{"想用 app.yaml<br/>最低維運快速上線?"}
  SIMPLE -->|"是"| STANDARD
  SIMPLE -->|"否"| REVIEW["重新比較 Cloud Run、GKE<br/>與其他運算服務"]
沒有容器、OS 控制或長連線的硬需求時,Standard 通常是較簡單且能縮至零的選擇;需要這些能力時再考慮 Flexible,容器工作負載也應同步比較 Cloud Run。
App Engine Standard 與 Flexible 比較:Standard 採受管 Sandbox 且啟動較快,Flexible 以 VM 上的 Docker 容器換取自訂 Runtime、SSH 與 OS 套件能力

先看 Runtime 與底層控制需求,再看擴縮速度。Standard 以受管 Sandbox 換取快速啟動與較少維運,是否縮至零取決於 scaling mode;Flexible 跑在 VM 上,可自訂 Runtime 與系統套件,但啟動較慢且至少維持一個 instance。


App Engine 結構

一個專案一個 App(不可撤銷)

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  PROJECT["GCP Project"] --> APP["唯一的 App Engine Application<br/>區域建立後不可更改"]
  APP --> DEFAULT["default Service<br/>必須存在"]
  APP --> API["api Service"]
  APP --> WORKER["worker Service"]
  DEFAULT --> V1["Version v1<br/>10% 流量"]
  DEFAULT --> V2["Version v2<br/>90% 流量"]
  API --> AV1["Version v1<br/>100% 流量"]
  WORKER --> WV1["Version v1<br/>100% 流量"]
一個專案只有一個 Application,但可拆成多個 Service;每個 Service 再保留多個不可變 Version,流量分割發生在同一服務的版本之間。

⚠️ 重要:

  • 每個 GCP 專案只能有 一個 App Engine Application
  • 建立後不能刪除(只能停用),也不能變更區域
  • default service 不能被刪除

📝 考場提點

規劃 App Engine 時,有兩個限制值得先確認:

  1. 區域建立後不可變更:選錯區域時,無法直接修改既有 App Engine Application 的位置;需要在其他專案重新建立,並規劃服務與資料遷移。
  2. 免費額度只適用特定配置:Standard 環境的部分執行個體有免費額度,但仍要核對機型、用量及其他資源費用;Flexible 環境沒有相同的免費層。

app.yaml 配置

# app.yaml(Standard 環境)
runtime: python312
instance_class: F2

automatic_scaling:
  target_cpu_utilization: 0.65
  min_instances: 0 # 設 0 才可能縮容至零
  max_instances: 10
  min_idle_instances: 1 # 常駐 1 個暖機實例(會持續計費,等於不會真的縮到零)

env_variables:
  ENVIRONMENT: 'production'

handlers:
  - url: /static
    static_dir: static/
  - url: /.*
    script: auto
# app.yaml(Flexible 環境)
runtime: custom
env: flex

resources:
  cpu: 2
  memory_gb: 4
  disk_size_gb: 20

automatic_scaling:
  min_num_instances: 1 # Flexible 不能是 0
  max_num_instances: 20

Instance Class(Standard 環境)

命名其實有邏輯,記住就好背了:F = Frontend,負責接使用者請求(搭配 Automatic Scaling);B = Backend,負責跑背景任務(搭配 Basic / Manual Scaling)。數字越大、記憶體和 CPU 越多。

Automatic Scaling(F-class)

用來接用戶請求、需要自動擴縮的服務:

Class記憶體CPU適合場景
F1384 MB600 MHz輕量 API、免費層用
F2768 MB1.2 GHz一般 Web 應用
F41.5 GB2.4 GHz運算密集型
F4_1G3 GB2.4 GHz記憶體密集型

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

Basic / Manual Scaling(B-class)

用來跑背景任務、排程工作:

Class記憶體CPU
B1384 MB600 MHz
B2768 MB1.2 GHz
B41536 MB2.4 GHz
B4_1G3072 MB2.4 GHz
B83072 MB4.8 GHz

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。


三種 Scaling 模式

1. Automatic Scaling(預設,Standard)

Compute Engine 代管執行個體群組的自動調度設定面板,調度模式為開啟自動調度、執行個體下限 1、上限 10、以 CPU 使用率 60% 作為調度信號,並可勾選預測式自動調度

先說清楚:這張是 Compute Engine 代管執行個體群組(MIG)的自動調度畫面,App Engine 沒有這種表單、一切都寫在下面的 app.yaml 裡——但背後的邏輯是同一套:訂一個 CPU 目標(圖中 60%,對上 YAML 的 target_cpu_utilization),再用下限、上限框住實例數。差別就在下限這格:MIG 這裡最低是 1,而 App Engine Standard 的 min_instances 可以壓到 0,這正是它能 scale-to-zero、把用量塞進免費層的關鍵。

automatic_scaling:
  target_cpu_utilization: 0.65
  target_throughput_utilization: 0.6
  min_instances: 0
  max_instances: 10
  min_idle_instances: 1 # 常駐暖機實例,減少冷啟動(會持續計費)
  max_idle_instances: 3 # 最多閒置實例
  max_concurrent_requests: 80

2. Basic Scaling

實例空閒一段時間後自動關閉:

basic_scaling:
  max_instances: 5
  idle_timeout: 5m # 閒置 5 分鐘後關閉

3. Manual Scaling

固定實例數,不自動擴縮:

manual_scaling:
  instances: 3
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START{"服務如何接收工作?"}
  START -->|"持續接 Web/API 請求"| AUTO["Automatic Scaling<br/>F-class"]
  START -->|"間歇背景工作<br/>空閒後可關閉"| BASIC["Basic Scaling<br/>B-class"]
  START -->|"固定容量、常駐處理"| MANUAL["Manual Scaling<br/>B-class"]
  AUTO --> SIGNAL["依 CPU、吞吐或並行請求<br/>在 min 與 max 間擴縮"]
  BASIC --> IDLE["收到工作才啟動<br/>idle timeout 後關閉"]
  MANUAL --> FIXED["永遠維持指定 instances"]
先看服務是前端請求、間歇背景工作或固定常駐容量,再對應 Automatic、Basic、Manual;F-class 與 B-class 的選擇也由這個模式決定。

版本管理與流量分割

部署新版本

# 部署並自動接收所有流量
gcloud app deploy

# 部署但不切換流量(測試用)
gcloud app deploy --no-promote --version=v2

# 查看所有版本
gcloud app versions list

流量分割(金絲雀發布)

金絲雀發布(canary release)=新版本先放一小部分流量試水溫,沒問題再慢慢放大,出事影響面也小。App Engine 用 --splits 就能做:

# 50/50 分流(沒指定 --split-by 時,預設依 IP 位址分配)
gcloud app services set-traffic default \
  --splits=v1=0.5,v2=0.5

# 90/10 分流(Cookie-based,同一用戶固定看到同版本)
gcloud app services set-traffic default \
  --splits=v1=0.9,v2=0.1 \
  --split-by=cookie

# 按 IP 分流
gcloud app services set-traffic default \
  --splits=v1=0.8,v2=0.2 \
  --split-by=ip

流量分割方式:

方式說明適合場景
random每次請求隨機分配A/B 測試
cookie同用戶固定版本(GOOGAPPUID cookie)功能漸進發布
ip同 IP 大致對應同一版本(IP 會變,不保證)簡單的金絲雀

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

回滾

# 將所有流量切回 v1
gcloud app services set-traffic default --splits=v1=1.0

# 停止舊版本(不再接收流量且釋放資源;gcloud 限制只有 manual scaling 的服務能 stop)
gcloud app versions stop v2

多服務架構(Services)

dispatch.yaml(路由規則)

# dispatch.yaml
dispatch:
  - url: '*/api/*'
    service: api
  - url: '*/admin/*'
    service: admin
  - url: '*/*'
    service: default
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  REQ["進入 App Engine<br/>的 HTTP 請求"] --> API{"符合 */api/*?"}
  API -->|"是"| APISVC["api Service"]
  API -->|"否"| ADMIN{"符合 */admin/*?"}
  ADMIN -->|"是"| ADMINSVC["admin Service"]
  ADMIN -->|"否"| DEFAULT["default Service<br/>*/* fallback"]
  APISVC --> AV["該服務目前接流量的<br/>Version"]
  ADMINSVC --> ADV["該服務目前接流量的<br/>Version"]
  DEFAULT --> DV["default 的流量分割版本"]
dispatch.yaml 先決定請求進入哪個 Service,Service 內部才依當前 traffic split 選擇 Version;最後的萬用規則讓未命中特定路徑的請求回到 default。
# 部署路由規則
gcloud app deploy dispatch.yaml

為不同服務配置不同 app.yaml

# 部署 default 服務
gcloud app deploy app.yaml

# 部署 api 服務(需在 app.yaml 中指定 service: api)
gcloud app deploy api/app.yaml

# 部署 worker 服務
gcloud app deploy worker/app.yaml

定期任務(Cron Jobs)

cron.yaml

# cron.yaml
cron:
  - description: 'Daily cleanup'
    url: /tasks/cleanup
    schedule: every 24 hours
    target: worker

  - description: 'Hourly report'
    url: /tasks/report
    schedule: every 1 hours

  - description: 'Weekly summary'
    url: /tasks/weekly-summary
    schedule: every monday 09:00
    timezone: Asia/Taipei
# 部署 cron 配置
gcloud app deploy cron.yaml

# 查看 App Engine 應用資訊(位置、預設網域、服務狀態)
# 註:cron 設定無 describe 指令,請至 Cloud Console(App Engine → Cron 工作)查看
gcloud app describe

App Engine 會在排程時間對指定 URL 發一個 HTTP GET 請求。請求的 header 會帶 X-Appengine-Cron: true,你可以用這個來驗證請求是不是真的從 cron 來的。

想用 unix-cron 語法排程的話,官方文件建議改用 Cloud Scheduler;cron.yaml 目前仍可使用。


定價

Standard 免費層(每天)

項目免費額度
F-class instance-hours28 小時/天
B-class instance-hours9 小時/天
儲存5 GB
對外流量1 GB/天

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

Standard 付費

Instance Class費用/小時
F1 / B1$0.05
F2 / B2$0.10
F4 / B4$0.20
F4_1G / B4_1G$0.30
B8$0.40

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

別把這幾個費率讀成各自獨立的價目:實際計費是「一個基準 instance-hour 費率 × class 倍數」。F1 是基準(約 $0.05),F2 是 2 倍、F4 是 4 倍,以此類推。所以你看到的數字其實都是同一個基準乘出來的,記倍數比記四個價格輕鬆。

Flexible

  • 無免費層
  • Per-second 計費(最少 1 分鐘)
  • 費用 = vCPU 費 + 記憶體費 + 磁碟費

所以 Flexible 通常只在你真的需要自訂 OS、特殊系統套件、或要撐長連線時才划算,不然多半比 Standard 貴。


暖機請求(Warm-up Requests)

新實例剛被叫起來、還沒載入快取和連線池時,第一個打進來的請求會特別慢,這就是冷啟動(cold start)。Standard 環境支援 warm-up request,讓新實例在接正式流量之前先「暖機」一下,把冷啟動的延遲吃掉:

# app.yaml
inbound_services:
  - warmup
# Flask 範例
@app.route("/_ah/warmup")
def warmup():
    # 預載快取、建立連線池等初始化動作
    initialize_caches()
    return "", 200, {}

App Engine 啟動新實例時,會盡量先打一個 GET /_ah/warmup(官方說不保證每次都會發),等你的應用程式初始化完成,才開始接正式請求。


遺留 Runtime 與遷移

遺留 Runtime 截止日期

Runtime狀態截止日
Python 2.7已停止新部署2026/01/31
Java 8已停止新部署2026/01/31
Go 1.11已停止新部署2026/01/31
PHP 5.5已停止新部署2026/01/31

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

2026 年 1 月 31 日起,這些 runtime 已經不能部署新版本了。已經跑著的應用在 2027 年 1 月 31 日(官方列的 Decommissioned 日期)前還會繼續運行,之後可能被停用,所以建議盡早遷移到第二代 Runtime(Python 3.12、Java 21、Go 1.25 等)。

遺留內建服務

服務狀態替代方案
Memcache APIlegacy 內建服務,Python/Java/Go/PHP 的第二代 runtime 仍可用Cloud Memorystore
Task Queue APIlegacy 內建服務,Python/Java/Go/PHP 的第二代 runtime 仍可用Cloud Tasks(push queue)、Pub/Sub(pull queue)
Blobstorelegacy 內建服務,Python/Java/Go 的第二代 runtime 仍可用Cloud Storage
Users APIlegacy 內建服務,Python/Java/Go/PHP 的第二代 runtime 仍可用Identity Platform / Firebase Auth

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

App Engine → Cloud Run 遷移

Google 有提供遷移工具(目前是 Beta),能依 app.yaml 產生 Cloud Run 的 service.yaml 並部署,適用沒用到 legacy 內建服務的第二代 runtime:

# 依 app.yaml 遷移到 Cloud Run(加 --dry-run 只檢查相容性、不實際部署)
gcloud beta app migrate-to-run --appyaml=app.yaml

# 或從既有 App Engine 服務直接遷移
gcloud beta app migrate-to-run --service=SERVICE --version=VERSION

無伺服器三劍客:最終選型決策

場景選擇理由
GCS 上傳觸發圖片處理Cloud Run functions事件驅動,單一函式
部署 REST API 微服務Cloud Run容器化,彈性語言
快速部署 Web App(MVP)App Engine Standard最簡單,一個 YAML
需要 WebSocketCloud Run 或 App Engine FlexibleStandard 不支援
需要 scale-to-zero 且非容器App Engine Standard有免費層
需要自訂 OS/DockerCloud Run最佳容器支援
長時間背景任務(> 60 min)Cloud Run Jobs最長 7 天

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START{"工作如何被觸發與執行?"}
  START -->|"事件觸發、單一短函式"| FUNCTIONS["Cloud Run functions"]
  START -->|"HTTP 服務或容器"| CONTAINER{"需要長時間背景批次嗎?"}
  CONTAINER -->|"是"| JOBS["Cloud Run Jobs"]
  CONTAINER -->|"否"| RUN["Cloud Run"]
  START -->|"傳統 Web App<br/>想用一個 YAML 快速上線"| CAP{"需要自訂 OS、Docker<br/>或 WebSocket 嗎?"}
  CAP -->|"否,並重視免費層"| STANDARD["App Engine Standard"]
  CAP -->|"是"| FLEXORRUN["優先 Cloud Run<br/>必要時 App Engine Flexible"]
觸發方式先分出 Functions,容器服務與長時間批次分別走 Cloud Run 和 Cloud Run Jobs;App Engine Standard 則保留給不需容器控制、重視快速部署與免費層的傳統 Web App。

📝 考場提點

題目中的部署方式和執行時間可以幫你縮小選項,但還要回頭檢查執行環境、連線方式與成本:

  • 單一事件處理函式,可先評估 Cloud Run functions。
  • 自訂容器或完整 Web/API 服務,可比較 Cloud Run service。
  • 現有應用符合 Standard 執行環境、想少管容器,可評估 App Engine Standard。
  • 需要 WebSocket,要確認服務的連線時間與擴縮方式;App Engine Standard 不支援,Cloud Run 與 App Engine Flexible 可納入比較。
  • 不需要持續接收請求的長時間背景工作,可評估 Cloud Run Jobs。

以上只是候選方向;最後仍要核對題目的具體限制。


ACE 考試重點整理

必背知識點

  1. 一個專案只能有一個 App Engine,建立後不可刪除、不可換區域
  2. Standard 可 scale-to-zero,Flexible 最少 1 個實例
  3. Standard 啟動秒級,Flexible 啟動分鐘級
  4. Standard 不支援 WebSocket
  5. F-class 用於 Automatic Scaling,B-class 用於 Basic/Manual Scaling
  6. 免費層:28 F-hours/天(夠跑一個小型應用)
  7. cron.yaml 排程任務,發送 HTTP GET 到指定 URL
  8. 遺留 runtime 已於 2026/01/31 停止新部署——Python 2.7、Java 8、Go 1.11、PHP 5.5 需遷移至第二代
  9. --no-promote 部署但不切流量,適合測試

常見陷阱題

Q:App Engine 部署後發現選錯區域,如何修改? A:無法修改。App Engine 的區域建立後不可更改,只能刪除整個 GCP 專案重建。

Q:需要支援 WebSocket 的即時聊天應用,用 App Engine Standard 還是 Flexible? A:Standard 不支援 WebSocket,應選 Flexible。或者更好的選擇是 Cloud Run。

Q:想讓 App Engine 完全不收費,怎麼做? A:使用 Standard 環境 + F1 instance class + min_instances: 0,在免費層 28 F-hours/天內使用。Flexible 無法免費(至少 1 實例)。

Q:部署新版本後發現 bug,如何快速回滾? A:gcloud app services set-traffic default --splits=PREVIOUS_VERSION=1.0。

Q:如何讓不同 URL 路由到不同服務? A:使用 dispatch.yaml 定義路由規則。


實戰範例:部署 Flask Web App

# main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html")

@app.route("/api/health")
def health():
    return {"status": "ok"}

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)
# app.yaml
runtime: python312
instance_class: F2
entrypoint: gunicorn -b :$PORT main:app

automatic_scaling:
  target_cpu_utilization: 0.65
  min_instances: 0
  max_instances: 5

env_variables:
  FLASK_ENV: 'production'
# requirements.txt
flask>=3.0
gunicorn>=22.0
# 部署
gcloud app deploy

# 開啟瀏覽器
gcloud app browse

# 查看日誌
gcloud app logs tail -s default

總結

如果正在評估 App Engine,可以先核對這些限制與設定:

  • Standard vs Flexible:兩者的執行環境、擴縮方式與費用不同,要依應用需求比較
  • 一個專案一個 App:不可刪除、不可換區域
  • Scaling:Automatic(F-class)、Basic、Manual(B-class)
  • 流量分割:--splits 支援 random/cookie/ip 三種方式
  • 免費層:Standard 28 F-hours/天
  • 定位:既有 App Engine 應用可沿用;新服務則與 Cloud Run、Cloud Run functions 一起比較

下一課 GCP-112:Firestore 入門:文件資料、即時更新與存取規則,接著看文件型資料庫的資料模型、查詢方式與權限設定。

運算服務選型系列

課程服務適合場景
GCP-109Cloud Run容器化 API/微服務,scale-to-zero
GCP-111Cloud Run functions事件驅動單一函式(GCS/Pub/Sub 觸發)
本課 ACE-212App Engine快速部署 Web App、免費層最多
ACE-206GKE完整 K8s 控制、大規模微服務
ACE-203綜合比較比較 App Engine、Cloud Run、GKE 的維運分工

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

ACE 服務實戰 — 第 7 篇/共 11 篇 查看系列全覽 →

讀完後,留一個學習紀錄

試著用自己的話說出一個重點,以及你會如何運用。實作文章請先核對結果與清理資源,再標記為讀完。

文章進度以你確認讀完的標記為準,可隨時取消。舊版造訪紀錄保留,但不計入讀完;這份自評不代表已掌握內容。

留言討論

文章目錄與系列

徽章解鎖!