iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Software Development

30 天把舊 ERP 整合成現代微服務平台:架構治理與工程實作雙軌實戰系列 第 10 篇

Day 10|Spring Cloud Gateway:Route、Predicate、Filter 如何分工

  • 分享至 

  • xImage
  •  

上一篇先整理了 Gateway 的責任,這一篇想把設定裡常見的三個名字分清楚:Route、Predicate、Filter。先知道誰負責哪一步,再看 YAML,會比較容易理解。

本篇名詞小筆記

  • Route:路由,定義請求符合條件後要被轉送到哪一個下游服務。
  • Predicate:判斷條件,用路徑、主機名稱或 Header 等資訊決定請求是否符合某條路由。
  • Filter:過濾器,在請求轉送前或回應送出前執行共用處理。
  • Circuit Breaker:在下游持續失敗時暫停呼叫,避免故障繼續擴大。
  • StripPrefix/RewritePath:兩種改寫路徑的 Filter,前者去掉路徑開頭幾段,後者依規則改寫,讓公開路徑不必等於內部路徑。

今天要解決的問題

如果少了說明,設定越加越多,後面就會越來越不敢動。所以我希望路由設定除了能跑,也能讓接手的人看懂:這條規則為什麼在這裡,修改之後會影響哪個服務。

下面用一段路由設定範例,對照這三個部分的位置:

spring:
  cloud:
    gateway:
      routes:
        - id: material-service
          uri: ${MATERIAL_SERVICE_URL:http://material-service:9095}
          predicates:
            - Path=/api/materials/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: ${RATE_MATERIAL_REPLENISH:80}
                redis-rate-limiter.burstCapacity: ${RATE_MATERIAL_BURST:160}
                redis-rate-limiter.requestedTokens: 1
                key-resolver: "#{@clientKeyResolver}"
                deny-empty-key: false

我會這樣讀這段設定:先用 id 找到路由對應的服務,負責人則回 Day 07 的 context card 查,再看 predicates 決定哪些請求會進來,最後看 filters 會做哪些處理。限流值由環境變數帶入,不同環境可以調整,預設值則留在版本紀錄裡;計數放在 Redis,多個 Gateway instance 才會共用同一份額度。

還有一行值得停下來看:deny-empty-key: false 表示算不出限流 key 的請求會放行。這裡的 key 來自呼叫端識別值,而 Day 09 說過 Gateway 會先驗 Token 基本有效性,沒有身分的請求在前一關就回 401,所以就算 key 算不出來也放行,不會出現「沒登入的人可以無限打」的漏洞。至於不用登入的路徑,抓不到 Token 就改用來源 IP 計數,所以 key 永遠算得出來,這個開關實際上不會用到,真正不能拆的是 IP 這層備援。如果限流跑在驗證之前,這一行就要改成 true。

架構師視角:路由設定就是對外契約

每條路由,我都會對回 Day 07 的 context card,確認服務與負責人,並把公開路徑和內部路徑分開管理。Filter 處理共用政策,敏感 Header 由 Gateway 控制;至於 timeout、retry 與 circuit breaker,再依 API 的特性安排。

https://ithelp.ithome.com.tw/upload/images/20260925/20184230wuIZD4cLi2.png

圖 Day 10-1:Spring Cloud Gateway 路由。

未知路徑也要測一次,確認帶有效 Token 時回的是預期的 404;因為 Security 先於路由執行,沒帶 Token 打未知路徑會先回 401,這是刻意不讓外部探到有哪些路由。如果有 fallback 路由,要再看看它會接住哪些請求,避免一條寫錯的路徑被轉送到不相關的後端。

若對外路徑直接等於內部服務結構,之後任何內部重構都會變成對外的破壞性變更。所以公開路徑與內部路徑要分開,讓對外契約可以獨立演進。

工程師視角:測試要涵蓋每一條政策

測試至少涵蓋正確路徑的路由、未知路徑 404、未驗證 401、無權限 403、限流 429,以及 Header 偽造、後端逾時與 correlation ID 傳遞。每項都要確認下游實際收到的內容與對外回應。

我自己會特別看下游實際收到了什麼。狀態碼正確,還不一定代表 Header 都處理好了;偽造的值有沒有被移除,correlation ID 有沒有帶到,都要一起驗證。

限流測試要先把「用誰的身分測試」固定下來。限流是按呼叫端計數的,今天用 A 的 Token 測、明天用 B 的,兩次結果就不能比。整輪測試都用同一個 Token,重跑幾次才對得起來。

策略取捨與限制

取捨 這樣選的理由 何時要重新評估
限流參數以環境變數覆寫 各環境門檻值不同,但預設值仍可追溯 環境間差異大到預設值失去參考價值時
不對非冪等請求設定自動 retry 重試可能建立重複交易 下游已具備冪等保證時(見 Day 19)
路由設定納入版本控管 變更可審查、可回溯 需要在執行期動態調整路由時
Predicate 不符合就回 404(帶有效 Token 時) 路徑寫錯時當場看到錯誤,不會悄悄被轉到別的服務 有明確的降級或維護頁需求時

有幾個設定,我會多停下來確認。寫入型 POST 如果沒有冪等保護,重試可能多建一筆交易;StripPrefix 與 RewritePath 則要對照公開契約,看看轉送後的路徑是不是原本想要的。

驗證方式與衡量指標

指標 計算方式 想回答的問題
各 route 流量分佈 依 route id 統計請求數 哪些路由實際被使用?
各 route 錯誤率 該 route 的 4xx/5xx 比率 問題集中在哪一條路由?
各 route P95 延遲 依 route id 統計延遲 哪一條路由是效能瓶頸?
設定變更紀錄 路由設定的 commit 與部署對應 行為改變能否對應到某次變更?

個別路由變慢或出錯,很容易被整體數字蓋過去,所以量測要依 route id 分開看。之後要能對照是哪次調整前後出現變化,設定異動也記下部署時間。

今天先整理到這裡

把路由、條件與前後處理分清楚,設定就比較容易看懂,也比較知道要測什麼。下一篇,再繼續整理呼叫者的身分,以及 Keycloak、OAuth 2.0、OIDC 與 JWT 各自的角色。

參考資料

  1. Spring, Route Predicate Factories,查閱日期:2026-09-23。
  2. Spring, GatewayFilter Factories,查閱日期:2026-09-23。

上一篇
Day 09|Gateway:統一入口,也是治理控制點
下一篇
Day 11|Keycloak、OAuth 2.0、OIDC 與 JWT:別再把登入和授權混在一起
系列文
30 天把舊 ERP 整合成現代微服務平台:架構治理與工程實作雙軌實戰 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言