簡介
在 Google Cloud 中,流量管理指的是有能力跨區域、跨服務、跨 revision 智能地路由、塑形 (shape)、鏡像 (mirror)、重試 (retry)、保護 HTTP/HTTPS 與 TCP 流量。它遠超過簡單的輪詢負載分配:透過 Application Load Balancer(舊稱 Global External HTTP(S) LB)、Internal Application Load Balancer、Cloud Run revisions、以及 Anthos Service Mesh (ASM),平台工程師可以實作 canary 發布、shadow traffic 流量鏡像、5xx 自動重試、stateful workload 的 sticky session、透過 Cloud DNS routing policies 做地理導向、以及 Envoy circuit breaker 隔離故障。PCNE 考試要求你知道每項功能屬於哪一層 load balancer、由哪個 API 欄位控制、以及 health check、IAP、Cloud Armor 擺在前面時會發生什麼。
白話文解釋
1. URL Map 像高鐵的轉乘月台
含 path matcher 的 URL map 就像高鐵轉乘車站。Forwarding rule 是驗 IP 與 port 的閘門;Target HTTPS Proxy 是撕 SSL 票根的查票員;URL map 則閱讀你票上的「目的地」(host header 與 path)並把你送到正確的月台(backend service)。/api/* 進 API 月台、/static/* 進 CDN 月台——沒有 URL map 你得為每個服務蓋一座獨立車站(一支 forwarding rule + 一個 IP)。
2. 加權後端服務像慢慢倒的咖啡品評
Weighted backend services 的行為像咖啡師讓你先用 5% 的劑量品嚐新配方。URL map 把 95% 的杯子(請求)送往老豆 (backend-v1)、5% 送往實驗豆 (backend-v2)。如果客人喜歡,再把刻度調到 25%、50%、100%。咖啡師(Envoy data plane)完全不必重編菜單——你只是改 route action 裡的 weight 整數,流量就在數秒內切換。
3. 流量鏡像像彩排
Request mirroring (requestMirrorPolicy) 是一場觀眾看不到的彩排:候補演員在第二個舞台上演出同一場戲。Production 流量仍然流向 backend-prod,但每一個請求的副本會被叉送到 backend-shadow(新版本)。Shadow 的回應會被丟棄,使用者完全不受影響,但你拿到真實世界的延遲、錯誤率、SQL plan 指標。在還沒撥動任何 user-facing 流量比例前,這是最安全的方式測試重寫版能不能扛得住 production 負載。
URL Map:Google Cloud Load Balancing 的一種資源,使用 host rules 與 path matchers 把進來的請求 URL(host + path)對應到 backend services 或 backend buckets。任何 Application Load Balancer 都需要它;Network Load Balancer (passthrough L4) 不使用 URL map。
URL Maps 與 Path Matchers 深入剖析
URL Map 的結構
一個 URL map 包含 defaultService(catch-all 後端)、零個以上的 host rules(每個把一組 hostname 對應到一個具名的 path matcher)、與 path matchers(內含 pathRules 與/或 routeRules)。當請求進來時,全球 Application Load Balancer 先評估 host rules,再依「最長 prefix 或顯式 priority」走訪 path matcher 內的規則。
gcloud compute url-maps create web-map \
--default-service=backend-default
gcloud compute url-maps add-path-matcher web-map \
--path-matcher-name=api-matcher \
--default-service=backend-default \
--path-rules='/api/*=backend-api,/static/*=backend-static' \
--new-hosts='www.example.com'
pathRules 與 routeRules 的差異
pathRules 是簡單形式(path glob → backend)。routeRules 是進階形式,支援 header 比對、query parameter 比對、加權目的地、URL rewrite、header 轉換、retry policy、fault injection、流量鏡像。只有 routeRules 才在全球外部 Application Load Balancer 上支援完整的進階流量管理。
Wildcard 與 Prefix 比對
Path matchers 採用相容 Envoy 的比對:prefixMatch、fullPathMatch、regexMatch。最長相符的 prefix 獲勝,顯式 priority 用於拆解平手。regexMatch 使用 RE2 語法——JavaScript 風格的 lookahead 不支援。
每個 path matcher 都要設定 安全的 defaultService。命中 host rule 卻所有 pathRule 都不符的請求會 fall through 到這個 default。把它指向一個靜態 404 後端,可避免 path 規則打字錯誤通過 code review 時暴露錯誤服務。
Header 路由與 Method 路由
routeRules 中的 headerMatches
Application Load Balancer 可以依任何 request header 分派流量。一個常見模式是把行動裝置客戶導到精簡後端:
routeRules:
- priority: 10
matchRules:
- prefixMatch: /
headerMatches:
- headerName: User-Agent
regexMatch: ".*Mobile.*"
routeAction:
weightedBackendServices:
- backendService: projects/p/global/backendServices/mobile-be
weight: 100
支援的 header operator 包括 exactMatch、prefixMatch、suffixMatch、regexMatch、presentMatch、rangeMatch、與 invertMatch。也可以透過 :authority、:method、:path 等 pseudo-header 對 cookie 做比對。
Method、Query Param、Pseudo-Header 比對
methodMatch 把規則侷限到 GET、POST 等——非常適合只把 POST /checkout 路由到 write-heavy 的後端 pool。queryParameterMatches 讓你依 ?canary=true 路由給選擇加入的 beta 測試,常搭配 feature flag,QA 在 URL 加上單一 query string 就能驗證新後端。
Header 轉換
在 routeAction.headerAction(或 pathMatcher.defaultRouteAction.headerAction)裡可以設定 requestHeadersToAdd、requestHeadersToRemove、responseHeadersToAdd、responseHeadersToRemove。這就是你用來蓋上 X-Cloud-Trace-Context 傳遞提示、或在回應離開 Google edge 前剝除內部 X-Debug-Token 的方法。
Header 路由是在 Google 的 Envoy fleet 內部、load balancer 層強制執行——不是在後端。這代表即使後端忽略該 header,你仍能切分流量。請搭配 Cloud Armor edge security policy,以防惡意客戶端偽造 header 繞過路由邏輯(例如永遠在 requestHeadersToRemove 移除客戶端送來的 X-Internal-Routing)。
加權後端服務與 Canary 發布
weightedBackendServices 如何運作
單一 routeRule 可以指向多個 backend service,每個帶整數 weight (0–1000)。Load balancer 把 weight 正規化成比例:95/5 拆分就是 weight: 95 與 weight: 5。Weight 是 per-request 套用、不是 per-connection,所以 HTTP/2 multiplexing 仍會遵守拆分。
gcloud compute url-maps import web-map --source=web-map.yaml
defaultRouteAction:
weightedBackendServices:
- backendService: .../backendServices/checkout-v1
weight: 95
- backendService: .../backendServices/checkout-v2
weight: 5
Progressive Delivery 管線
典型 canary 管線:把新版烤進 checkout-v2、部署時 weight: 0、透過 headerMatches 跑 smoke test(只有帶 X-Canary: true 的請求進 v2)、然後分階段拉高到 1%、5%、25%、50%、100%,同時在 Cloud Monitoring 監看 SLO error budget 燃燒。Rollback 只需一次 gcloud compute url-maps import——不用重部、不用等 DNS TTL。
加權路由的支援與不支援
Weighted backend services 在 全球外部 Application Load Balancer、區域外部 Application Load Balancer、Internal Application Load Balancer(區域、跨區域)皆可用。不支援在 classic Network Load Balancer (passthrough L4)、舊版未啟用進階流量管理的全球 HTTPS LB、Internal TCP/UDP LB 的協定 forwarding rule。
考生常因「Network Load Balancer」與高效能一起出現,就選它當 canary 答案。錯——Passthrough Network Load Balancer 只能依 5-tuple 路由,沒有 URL map、沒有 weight 欄位。L4 層的 canary 是加權 DNS 或加權 forwarding rule IP,不是加權後端。
Cloud Run 上的流量拆分
Revisions 與 Tagged URL
Cloud Run 把每次部署當作不可變的 revision。gcloud run services update-traffic 指令在 revision 之間切換比例,完全不動 container、不重建 image。
gcloud run services update-traffic checkout \
--to-revisions=checkout-00042-abc=90,checkout-00043-def=10 \
--region=asia-east1
--tag 用於 Pre-Production 探測
每個 revision 可以拿到一個 tag,會鑄出一個 tag 專屬 URL,如 https://canary---checkout-xyz.a.run.app。Tagged URL 預設拿到 0% production 流量,所以 QA 可以直接打新 revision,而真實使用者仍看到穩定 revision。搭配 --no-traffic 可以部署但完全不暴露新 revision。
漸進式 Rollout 與 Rollback
Cloud Run 在 traffic mode 為 LATEST 時支援 gradual rollout,但顯式 per-revision 拆分是確定性的、是考題提到「5% canary 接著 25%」時應選的答案。Rollback 就是 gcloud run services update-traffic checkout --to-revisions=checkout-00042-abc=100——即時且原子。
當 Cloud Run 擺在 External Application Load Balancer 加 Serverless NEG 後面時,你有兩個獨立的流量拆分層:URL map 的 weightedBackendServices 以及 Cloud Run revision 拆分。請擇一管理 canary,否則出事故時複合百分比(95% × 90% = 85.5%)會讓人難以推理。
流量鏡像 (requestMirrorPolicy)
Mirroring 做什麼
routeRule 可以加上 requestMirrorPolicy,指定一個次要 backend service。每個命中的請求會同時送到主 backend(回應給使用者)與鏡像 backend(回應丟棄)。鏡像的延遲不影響使用者;鏡像的失敗不被重試;鏡像看到的是完全一樣的 request body 與 header,X-Forwarded-For 也會保留。
使用情境
- 重寫版 shadow-testing:把 100% production 流量同時送到
payments-v1(live)與payments-v2(mirror),比對指標後再用加權路由切換。 - Schema 遷移驗證:把寫入鏡像到新的 Cloud SQL 實例,比對 query plan 而不影響使用者。
- 資安掃描:鏡像給一個跑深度封包檢測或 detect-only WAF 的後端。
限制
鏡像流量會計入鏡像 backend 的容量與配額——你必須把它放大到能扛全部複製的請求量。鏡像 endpoint 應該是 idempotent,因為 POST/PUT/DELETE 會執行兩次。Mirroring 在全球外部 Application Load Balancer 與區域 Application Load Balancer 上透過 routeAction.requestMirrorPolicy 提供。
Mirroring 會把真實 production 資料(含 request body 中的 PII)送到 shadow backend。如果鏡像位於不同 VPC、project 或 region,請確保等效的 DLP scanning、VPC Service Controls perimeter 成員資格、IAM least privilege 都到位,否則 mirroring 會變成資料外洩管道。
Retry Policies 與 Timeouts
routeAction 的 retryPolicy
在 Envoy data plane 內部設定自動 client-side retry:
routeAction:
retryPolicy:
retryConditions:
- 5xx
- gateway-error
- connect-failure
- retriable-4xx
numRetries: 3
perTryTimeout: 5s
有效的 retryConditions 包括 5xx、gateway-error、connect-failure、retriable-4xx(只有 409)、refused-stream、cancelled、deadline-exceeded、internal、resource-exhausted、unavailable。如果設定 retryPolicy 但沒指定 numRetries,預設是 1。
Backend Service Timeout
gcloud compute backend-services 的 --timeout 旗標(全球外部 Application Load Balancer 預設 30 秒)控制 load balancer 等待後端回應的時間。WebSocket 與 long-poll 後端應該用 --timeout=86400 拉高到 86400 秒(24 小時)。
Connection Draining
--connection-draining-timeout 控制後端被移除時 in-flight 請求能繼續排空多久(預設 0 秒,最大 3600 秒)。在滾動更新 MIG instance 時,把它設成 p99 請求時間加上緩衝,使用者就不會在部署期間看到 502。
Idle Timeout 與 HTTP Keepalive
全球外部 Application Load Balancer 預設保持 HTTP keepalive 連線 610 秒;後端 keepalive 由 --connection-draining-timeout 與 backend service 的 HTTP/2 設定控制。LB 與後端 keepalive 不一致是間歇性 502 的頭號來源。
Application Load Balancer 預設 timeout — backend service response timeout 30 秒、HTTP keepalive (frontend) 610 秒、connection draining 0 秒、有 retryPolicy 但未設 numRetries 時為 1。背下這四個數字:PCNE 很愛問「WebSocket 每 5 分鐘斷一次該調哪個旋鈕?」(答案:backend service --timeout 拉高到 86400 秒)。
透過 Anthos Service Mesh 做 Circuit Breaker
為什麼需要 Circuit Breaker
Application Load Balancer 的 backend service 透過 backend service 資源的 circuitBreakers 支援基本容量控制 (maxConnections、maxPendingRequests、maxRequestsPerConnection、maxRetries)。但要做 outlier detection、把壞掉的 pod 黏性踢出、以及 mesh 全域 policy,就要升級到 Anthos Service Mesh (ASM)——Google 託管的 Istio。
Istio DestinationRule 的 Connection Pool 與 Outlier Detection
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: checkout-circuit
spec:
host: checkout.prod.svc.cluster.local
trafficPolicy:
connectionPool:
tcp: { maxConnections: 100 }
http: { http1MaxPendingRequests: 100, maxRequestsPerConnection: 10 }
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
一個 pod 在 30 秒內連續回傳 5 個 5xx,就會被踢出 load balancing pool 30 秒。ASM 把踢除上限設在 healthy endpoint 的 50%,這樣 flapping service 沒辦法把自己整個下線。
Backend Service circuitBreakers(LB 層)
在 load balancer 層用 gcloud compute backend-services update 設定同樣的基本參數:
gcloud compute backend-services update checkout-be \
--global \
--max-connections=1000 \
--max-pending-requests=100 \
--max-requests-per-connection=10
LB 層 circuit breaker 用於 north-south(網際網路 → 服務),ASM 用於 east-west(服務 → 服務)。
ASM 的 outlier detection 是 per-Envoy-sidecar 本地視角,不是全球同步。同一個 pod 可能被某個 client 的 pool 踢出,但其他 client 仍把流量送過去——這是刻意設計的,避免同步性 flapping。別期待每個 client 在同一毫秒踢同一個 pod;請搭配 health check 驅動的 Kubernetes liveness probe 做硬性移除。
Session Affinity 選項
各 Load Balancer 類型的 Affinity 模式
Backend service 的 sessionAffinity 欄位可選:
NONE——純負載平衡(預設)。CLIENT_IP——對 client IP 做 hash(L4 與 L7 LB)。CLIENT_IP_PROTO——IP + protocol(僅 L4 LB)。CLIENT_IP_PORT_PROTO——5-tuple(僅 L4 internal passthrough)。GENERATED_COOKIE——LB 發GCLBcookie(HTTP(S) LB)。HEADER_FIELD——對指定 request header 做 hash(具備進階流量管理的 HTTP(S) LB)。HTTP_COOKIE——對客戶提供的 cookie 名稱做 hash(具備進階流量管理的 HTTP(S) LB)。STRONG_COOKIE_AFFINITY——HTTP cookie affinity,後端變動時仍能存活(部分 LB)。
affinityCookieTtlSec
對 GENERATED_COOKIE 與 HTTP_COOKIE,TTL 預設 0(session cookie,瀏覽器關閉即清除)。把 affinityCookieTtlSec 設成一個固定視窗,可以把使用者釘住一段時間——後端記憶體裡放購物車這類 stateful 場景很實用。
Affinity 與 Balancing Mode 的拉扯
Affinity 是 盡力而為:如果後端因 balancingMode (UTILIZATION、RATE、CONNECTION) 變成不健康或容量飽和,LB 會挑新後端,session 就斷了。要真正持久,請把狀態外部化到 Memorystore Redis 或 Cloud Spanner,affinity 只當延遲優化。
透過 Cloud DNS Routing Policy 做地理導向
Geo Routing Policy
Cloud DNS routing policies 讓單一 DNS 名稱依詢問解析器的地理位置回不同 IP。用 per-region rrdataSets 定義 policy:
gcloud dns record-sets create www.example.com. --zone=prod-zone \
--type=A --ttl=60 \
--routing-policy-type=GEO \
--routing-policy-data="asia-east1=10.1.0.10;europe-west1=10.2.0.10;us-central1=10.3.0.10"
台灣的解析器收到 10.1.0.10,法蘭克福的收到 10.2.0.10。它與 anycast Application Load Balancer IP 互補:為法規遵循或延遲釘選場景提供明確區域控制。
WRR (Weighted Round Robin) Policy
DNS 層在多個區域 ALB 之間做 canary:
--routing-policy-type=WRR \
--routing-policy-data="90=34.117.x.x;10=34.149.y.y"
Failover Policy
主要區域 VIP 加上備援 VIP,只在 Cloud DNS health check 失敗時啟用。注意:DNS-based failover 受 TTL 約束(請設 30–60 秒),所以全球 anycast Application Load Balancer 仍是次秒級 failover 的首選。
把 Cloud DNS Geo policy 跟 區域 Application Load Balancer 結合,可以在不犧牲 URL map 進階流量管理的前提下,滿足資料駐留法規(EU 流量在 europe-west1 收斂、APAC 在 asia-east1)。全球 ALB 的單一 anycast IP 本身無法強制區域資料駐留。
串起來:一個 Production 拓樸
一個現實的 PCNE 規模拓樸會把這些功能層層疊起:
- Cloud DNS Geo policy 把 EU 使用者導到
europe-west1區域外部 Application Load Balancer、APAC 導到asia-east1。 - 每個區域 ALB 的 URL map 都有 path matcher:
/api/*→ API backend (Serverless NEG 後的 Cloud Run)、/static/*→ backend bucket (Cloud Storage + Cloud CDN)、default → 前端 MIG。 - API path matcher 用 routeRules,以
X-Canary: true的headerMatches把選擇加入的流量 100% 送到api-v2,其餘以weightedBackendServices95/5。 requestMirrorPolicy把/api/checkout100% 鏡像到api-shadow,做 production 等級測試。retryPolicy對5xx與gateway-error重試 3 次,每次 5 秒 per-try timeout。- Backend service
circuitBreakers上限 1000 connections;ASMDestinationRule在 microservice 之間處理 east-west outlier ejection。 sessionAffinity: GENERATED_COOKIE加上affinityCookieTtlSec: 3600把 stateful 購物車釘住。
考試尖兵與陷阱
- 陷阱:「URL map 可用於 Network Load Balancer。」錯誤。URL map 用於 Application Load Balancer (L7)。Passthrough Network Load Balancer (L4) 沒有 URL map。
- 提示:Canary 場景找 weighted backend services 或 Cloud Run 用
update-traffic切 revision。 - 提示:在不影響使用者下做 shadow-test,找
requestMirrorPolicy。 - 提示:次秒級區域 failover 首選 全球 anycast Application Load Balancer,不是 Cloud DNS failover policy。
- 提示:對暫時性
5xx自動重試,設定retryPolicy.retryConditions含5xx與gateway-error。 - 提示:Mesh 內 circuit breaker 答案是 ASM
DestinationRule.outlierDetection,不是 LB backend service 的circuitBreakers。
常見問題
URL map 內的 Host Rule 與 Path Rule 有什麼差異?
Host rule 依 Host header 路由(如 blog.example.com vs shop.example.com)並選出一個 path matcher。Path rule 住在 path matcher 裡,依 URL path 路由。兩者都必要:hostRule → pathMatcher → pathRule/routeRule → backendService。
我可以在同一個 URL map 內拆分 Cloud Run 與 GKE 後端的流量嗎?
可以。用一個 weightedBackendServices routeRule 指向 Serverless NEG (Cloud Run) 與 zonal NEG 或 Instance Group (GKE)。Application Load Balancer 在加權時把它們視為同質的 backend service。
requestMirrorPolicy 會讓我的後端成本加倍嗎?
對鏡像服務來說,是的——鏡像請求會吃 CPU、記憶體、下游呼叫 (Cloud SQL、BigQuery 等)。鏡像 backend 請以主 backend 100% 容量規劃,並假設執行需 idempotent。
HTTP_COOKIE affinity 跟 GENERATED_COOKIE 有什麼不同?
GENERATED_COOKIE 由 Google 的 load balancer 鑄造與管理(GCLB cookie)。HTTP_COOKIE 使用客戶提供的 cookie 名稱與 path,讓你的應用程式自行管理 cookie 生命週期,並能在非 LB 路徑上傳遞(例如 CDN 到 origin 之間)。
什麼時候該用 Anthos Service Mesh circuit breaker 而不是 backend service circuitBreakers?
當流量是 east-west(mesh 內 service-to-service)、需要 outlier detection(依連續 5xx 把不健康 endpoint 踢出)、想要透過 DestinationRule CRD 管理 mesh 全域 policy 時用 ASM。Backend service circuitBreakers 適合 north-south 入口流量在 LB 層的容量上限。
Retry policy 會重試 POST 請求嗎?
會——Envoy 對任何符合 retryConditions 的方法都會重試。對非 idempotent 操作(重複扣信用卡)來說 POST 重試很危險。請讓 endpoint idempotent(idempotency key),或用獨立 routeRule 加 methodMatch,把 retryPolicy 限縮到安全的 method。
Weight 顆粒度多細——可以 0.5% 嗎?
Weight 是 0–1000 的整數,Envoy 把它們正規化到總和。0.5% 拆分要寫 weight: 5 與 weight: 995。要做到次 0.1%,得在 DNS 層 WRR 或 per-region scaling 上動手腳。