Gateway路由網關詳解
一、Gateway路(lu)由網關:
Spring Cloud Gateway 是 Spring Cloud 生態中的 API 網關組件,專為微服務(wu)架構設計,基于(yu)響應式編程(cheng)模型(Reactive Programming)構建,使用(yong) Netty 作(zuo)為運行時(shi)環境,提供動態路(lu)由、安全、監控、限(xian)流等核心功能。

Spring Cloud Gateway的(de)設計理(li)念(nian)和存在意(yi)義圍繞微服務(wu)架構(gou)的(de)核心訴求展開(kai),旨在解決分(fen)布式系統中 API 管理(li)的(de)復雜性,其核心目標可歸(gui)納(na)為(wei)以下幾點:
1、統一流量治理入口:
|
意義 |
微服務架構中服務數量激增,直接暴露所有服務端點存在安全風(feng)險和(he)管理混亂問題(ti) |
|
方案 |
作為統一入口,收(shou)斂所有(you)內部服(fu)務的(de) API 暴露,對外提(ti)供(gong)標準化的(de)訪問路徑,屏蔽內部服(fu)務細節(jie)(如(ru)服(fu)務名、實例(li)地址(zhi)) |
2、動態化與可編程性:
|
設計理念 |
|
支持通過(guo)配置(YAML/Java DSL)或代碼動態定義路由規則、過(guo)濾器鏈,無(wu)需重啟服務。 結(jie)合 Spring Cloud Config 或 Nacos 等配置(zhi)中心,實現(xian)路由規(gui)則的實時更新,適應服(fu)務擴縮容(rong)、灰度發布等場(chang)景。 |
3、深度集成 Spring 生態:
|
意義 |
與 Spring Cloud 組件(jian)(如服務發(fa)現、熔斷器、安全框(kuang)架)無(wu)縫(feng)協作,降低技術棧復雜度 |
|
典型場景 |
自(zi)動從(cong) Eureka/Nacos 獲取服(fu)務(wu)實例列(lie)表,實現動態(tai)路由。 整合 Sentinel 實(shi)現(xian)熔斷(duan)降級,或(huo)通過 Spring Security 集中鑒(jian)權。 |
4、非阻塞高性能架構:
|
設計理念 |
|
基于(yu)響(xiang)應式編程模型(Reactive,使用 WebFlux 和 Reactor),采用非阻塞(sai) I/O,避免傳統同步阻塞(sai)網關(如 Zuul 1.x)的線程資源瓶頸。 適(shi)應高并發(fa)、低(di)延遲場景(如物聯網(wang)、實時通信),提升系統(tong)吞(tun)吐量。 |
5、靈活擴展與定制:
|
意義 |
通(tong)過(guo)過(guo)濾器鏈(lian)機制,允許開發者自(zi)定義邏輯(如限流算法、日(ri)志格(ge)式) |
|
擴展點 |
全局過濾器(Global Filter):適用于所有路由(如(ru)統一(yi)鑒(jian)權、日(ri)志記錄)。 路由過(guo)濾器(Route Filter):針對特(te)定路由的定制邏(luo)輯(如路徑重寫、請求頭修改)。 |
6、云原生友好性:
|
設計目標 |
適配 Kubernetes、Service Mesh 等云(yun)原生環境 |
|
特性 |
輕量級部署,支持容器化。 與服務(wu)網格(如(ru) Istio)互補,處理南北(bei)流量(網關)與東西流量(Sidecar)的分工協作。 |
二(er)、Gateway核(he)心(xin)概念(nian):
1、Gateway三大核心:
|
Route(路由) |
路由(you)是構建網關(guan)的(de)基本模(mo)塊,由(you)ID,目標URI,一系列(lie)的(de)斷言(yan)和過濾器組成 |
|
Predicate(斷言(yan)) |
開發人員可以匹(pi)配HTTP請(qing)求(qiu)中的所有(you)內(nei)容(rong)(例(li)如請(qing)求(qiu)頭或請(qing)求(qiu)參(can)數),如果請(qing)求(qiu)與斷言相匹(pi)配則進行路由 |
|
Filter(過(guo)濾) |
使用過濾器,可以在請求(qiu)(qiu)被路由前或者之后對請求(qiu)(qiu)進(jin)行(xing)修改 |
2、Gateway工作原理:
Spring Cloud Gateway 作為(wei)微服務架構(gou)的(de) API 網關(guan),其核心處(chu)理(li)流(liu)程(cheng)為(wei):當客(ke)戶端請(qing)(qing)求到達時,網關(guan)基于預設的(de)路(lu)由規則(如(ru)路(lu)徑(jing)、請(qing)(qing)求頭等(deng)斷言條件)匹配目(mu)標服務,隨后(hou)(hou)通(tong)過過濾(lv)器(Filter)鏈(lian)對請(qing)(qing)求進行預處(chu)理(li)(如(ru)鑒(jian)權、限(xian)流(liu)、路(lu)徑(jing)重寫(xie)),以非阻塞方式(底層基于 Netty 的(de)非阻塞 I/O 模型(xing)(xing)處(chu)理(li)連(lian)接(jie),利(li)用 Reactor 線程(cheng)模型(xing)(xing)實現高(gao)并發(fa))將(jiang)(jiang)請(qing)(qing)求轉發(fa)至(zhi)后(hou)(hou)端服務;待服務響應后(hou)(hou),再經(jing)后(hou)(hou)置過濾(lv)器加工(如(ru)修(xiu)改響應頭、統一錯誤(wu)格式),最終(zhong)將(jiang)(jiang)結(jie)果返(fan)回(hui)客(ke)戶端,全程(cheng)依(yi)托 Spring WebFlux 的(de)響應式模型(xing)(xing)實現高(gao)性(xing)能和動態路(lu)由能力(li)。

三(san)、實戰:
1、斷言重寫路由:
(1)、解(jie)耦(ou)客戶(hu)端(duan)與后端(duan)服務,提升系統(tong)靈活(huo)性。
(2)、統一 API 入口,簡化客(ke)戶端調用邏輯。
(3)、動態適配后端服(fu)務路徑,支持服(fu)務獨立演進。
(4)、集成負載均衡(heng)和(he)服務發(fa)現,提升系統(tong)可(ke)用性。
(5)、集中管(guan)理安(an)全與(yu)流(liu)量控制,降低維護成本。

網關配置文件bootstrap-one.yml:
#斷言(yan)重寫(xie)路由配置 # 假設有一個走網關請(qing)求 URL 是(shi) http://localhost:9090/api/provider/v1/resource,根據上述(shu)配置: # 1、匹配: # 請求路(lu)徑(jing) /api/provider/v1/resource 匹配 Path=/api/provider/** 斷(duan)言。 # 2、重寫路(lu)(lu)(lu)徑: # 使用(yong) RewritePath 過(guo)濾器將路(lu)(lu)(lu)徑從 /api/provider/v1/resource 重寫為(wei) /provider/v1/resource。 # 3、轉(zhuan)發: # 最(zui)終(zhong)請(qing)求將被轉(zhuan)發到(dao) lb://cloud-provider-service/provider/v1/resource。 # 對外暴露端口 server: port: 9090 spring: #項目(mu)名 application: name: cloud-gateway-service cloud: nacos: config: server-addr: localhost:8848 file-extension: yaml # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # context-path: /nacos # username: nacos # password: nacos discovery: server-addr: localhost:8848 # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # username: nacos # password: nacos #############################網關(guan)配(pei)(pei)置########################### gateway: # 服(fu)務(wu)(wu)(wu)路(lu)(lu)(lu)由(you)配(pei)(pei)置(路(lu)(lu)(lu)由(you)是構建網關(guan)的(de)基(ji)本模塊(kuai),由(you)ID,目(mu)標URI,一(yi)系列的(de)斷(duan)言和(he)過(guo)濾器組成) routes: # 路(lu)(lu)(lu)由(you)的(de)ID,沒有固定規則但要求唯一(yi),建議配(pei)(pei)合服(fu)務(wu)(wu)(wu)名 - id: cloud-provider-service # 路(lu)(lu)(lu)由(you)的(de)地址,lb表示使用(yong)負載均(jun)衡(引(yin)入負載均(jun)衡依賴(lai))到(dao)微服(fu)務(wu)(wu)(wu),也可以使用(yong)http正(zheng)常轉(zhuan)發 # uri: lb://服(fu)務(wu)(wu)(wu)注冊中心注冊的(de)服(fu)務(wu)(wu)(wu)名稱 # uri: //localhost:8080 uri: lb://cloud-provider-service #斷言工廠列表: predicates: - Path=/api/provider/** filters: # 重(zhong)寫路由(you):使用 RewritePath 過(guo)濾(lv)器將路徑從(cong) /api/provider/(?<segment>.*) 重(zhong)寫為 /provider/$\{segment}。 # 內(nei)部訪問地(di)址://localhost:8080/provider/** # 網關訪問(wen)地(di)址://localhost:9090/api/provider/** - RewritePath=/api/provider/(?<segment>.*), /provider/$\{segment} - id: cloud-consumer-service uri: lb://cloud-consumer-service predicates: - Path=/api/consumer/** filters: - RewritePath=/api/consumer/(?<segment>.*), /consumer/$\{segment}
注:
使用lb做(zuo)負(fu)載均衡需引(yin)入相關(guan)依賴
<!--負載均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
2、令牌桶算法限流過濾器:
在微服(fu)務(wu)架構(gou)中,網關作為(wei)所有請求(qiu)的(de)入口(kou)點,承擔著路由、認證、安全等職責(ze)。隨著業務(wu)規模的(de)擴大和用(yong)戶量的(de)增(zeng)(zeng)長(chang),請求(qiu)流量會顯著增(zeng)(zeng)加,這(zhe)可(ke)(ke)能(neng)導致后端服(fu)務(wu)過(guo)載,影響系統的(de)穩(wen)定性(xing)和響應時(shi)間。在網關層進行(xing)限流過(guo)濾器的(de)部(bu)署,可(ke)(ke)以有效(xiao)保護(hu)后端服(fu)務(wu),提(ti)升用(yong)戶體(ti)驗,優化資源分配,并增(zeng)(zeng)強系統的(de)整體(ti)穩(wen)定性(xing)。通過(guo)這(zhe)種方式,可(ke)(ke)以更好地(di)應對高并發(fa)場景(jing),確(que)保系統的(de)可(ke)(ke)靠性(xing)和性(xing)能(neng)。
(1)、網關層限流過濾器的優點:
1)、控制請求(qiu)速率:平滑(hua)地(di)控制請求(qiu)發送(song)速率,防止瞬時(shi)高流量沖擊系統。
2)、保(bao)障穩定(ding)(ding)性(xing):避(bi)免后端服務(wu)過載,確保(bao)系統(tong)的(de)穩定(ding)(ding)性(xing)和可用性(xing)。
3)、公平(ping)分(fen)配資源:合理分(fen)配系(xi)統資源,確保(bao)每個服(fu)(fu)務都能獲得(de)公平(ping)的服(fu)(fu)務響應(ying)時間。
4)、支持突發(fa)流(liu)量:允(yun)許一(yi)定程(cheng)度的突發(fa)流(liu)量,同時保持長期穩定的請求處(chu)理能力。
5)、靈(ling)活配置:可以根(gen)據業(ye)務(wu)需求動態調整限流策略,適(shi)應(ying)不同的應(ying)用場景。
(2)、Gateway-RequestRateLimiter限流的實現原理:
Spring Cloud Gateway 的 RequestRateLimiter 基(ji)于令(ling)(ling)(ling)牌(pai)桶算法實現(xian)分(fen)布(bu)式(shi)限(xian)流(liu)(liu),其原理(li)是:通(tong)過 redis-rate-limiter 集成 Redis,系(xi)統以固定(ding)速率(replenishRate,如(ru)每(mei)秒 5 個(ge)(ge)令(ling)(ling)(ling)牌(pai))向令(ling)(ling)(ling)牌(pai)桶填充令(ling)(ling)(ling)牌(pai),桶容量(liang)(liang)上限(xian)為 burstCapacity(如(ru) 10 個(ge)(ge)令(ling)(ling)(ling)牌(pai)),允許突發(fa)流(liu)(liu)量(liang)(liang)短時(shi)消耗積累的令(ling)(ling)(ling)牌(pai);當(dang)每(mei)個(ge)(ge)請(qing)求(qiu)到達時(shi),網關通(tong)過 Redis 原子(zi)化操作(Lua 腳本)檢查當(dang)前請(qing)求(qiu)的限(xian)流(liu)(liu)鍵(jian)(由 key-resolver 定(ding)義(yi),如(ru)按(an) IP 生成唯一鍵(jian))嘗(chang)試從桶中獲取(qu)令(ling)(ling)(ling)牌(pai),若桶中存在可用令(ling)(ling)(ling)牌(pai)則(ze)放(fang)行并扣除令(ling)(ling)(ling)牌(pai),否則(ze)觸發(fa)限(xian)流(liu)(liu)(返回 HTTP 429),借助 Redis 的分(fen)布(bu)式(shi)存儲和原子(zi)性特性,確保多網關實例間(jian)的限(xian)流(liu)(liu)狀態嚴(yan)格一致,實現(xian)高并發(fa)場景(jing)下精(jing)準、靈活的流(liu)(liu)量(liang)(liang)控制。
(3)、令牌桶算法與漏桶算法:
|
對比維度 |
令牌桶算法 |
漏桶算法 |
|
核心思想 |
以固(gu)定速率生(sheng)成(cheng)令牌,請求(qiu)需獲取令牌才能通過。 |
以(yi)恒定速率處(chu)理請(qing)求,超出速率的請(qing)求排(pai)隊或丟(diu)棄。 |
|
流量特性 |
允許突發(fa)流量(桶內令牌(pai)可累積)。 |
強制(zhi)平滑流量(恒定速率輸出,無法應對(dui)突發)。 |
|
實現復雜度 |
簡單(僅需管理令牌生成(cheng)和(he)消耗)。 |
較高(需維護請求隊列和漏出(chu)速(su)率)。 |
|
適用場景 |
需要容(rong)忍突發(fa)流量的場(chang)景(如秒殺、API 突發(fa)調用)。 |
需嚴(yan)格限制請求(qiu)速率的場景(如(ru)音視頻流(liu)控)。 |
|
資源利用率 |
高(gao)(突發期(qi)可快速消費(fei)累積令(ling)牌)。 |
低(嚴格限速可能導致帶寬浪(lang)費)。 |
|
典型工具 |
Spring Cloud Gateway、 Google Guava RateLimiter |
Nginx 限流(liu)模塊(kuai)、 pache 的 mod_ratelimit |
(4)、相關實現:
1)、POM依賴:
|
特性 |
spring-boot-starter-data-redis-reactive |
spring-boot-starter-data-redis |
|
編程模型 |
響應式(Reactive) |
同步(Blocking) |
|
客戶端 |
Lettuce(強(qiang)制) |
Lettuce/Jedis(可選(xuan)) |
|
適用場景 |
高并發、非阻塞(sai) I/O |
常規同步操作 |
<!-- Redis Reactive 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2)、YML配置文件:bootstrap-two.yml
集成(cheng)Redis配置令牌桶限流機制:
指定令牌填(tian)充速(su)度replenishRate、令牌桶(tong)容量burstCapacity、限流策略KeyResolver
#令牌(pai)(pai)桶算(suan)法限流過濾器 # 令牌(pai)(pai)桶的基本(ben)邏輯是: # 每個(ge)IP對應(ying)一個(ge)桶,桶里有令牌(pai)(pai),每秒(miao)補充一定的令牌(pai)(pai)數,最多(duo)不超過桶的容量。當請求(qiu)到(dao)來時,如果桶里有足夠的令牌(pai)(pai),則允許通過并消耗一個(ge)令牌(pai)(pai),否則拒(ju)絕。 # 對外(wai)暴露端口 server: port: 9090 spring: #項(xiang)目名 application: name: cloud-gateway-service cloud: nacos: config: server-addr: localhost:8848 file-extension: yaml # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # context-path: /nacos # username: nacos # password: nacos discovery: server-addr: localhost:8848 # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # username: nacos # password: nacos #############################網關配(pei)置########################### gateway: # 服(fu)務路由配(pei)置(路由是構建網關的(de)基(ji)本模(mo)塊,由ID,目標URI,一系列的(de)斷言和過濾器組成) routes: # 路由的(de)ID,沒有(you)固定規(gui)則但要求唯一,建議(yi)配(pei)合服(fu)務名(ming) - id: cloud-provider-service # 路(lu)由的地(di)址,lb表(biao)示使(shi)用負載均(jun)衡(引入負載均(jun)衡依賴)到微(wei)服務,也可以使(shi)用http正常轉發 # uri: lb://服(fu)務注(zhu)冊(ce)(ce)中(zhong)心注(zhu)冊(ce)(ce)的(de)服(fu)務名稱 # uri: http://localhost:8080 uri: lb://cloud-provider-service #斷言工廠列(lie)表: predicates: - Path=/provider/** filters: # 限流過濾器 - name: RequestRateLimiter args: # 填充速率,每秒允許通過請求數 redis-rate-limiter.replenishRate: 5 # 令牌桶容量,系統允許的突發請求量,即短時間內可以處理的最大請求數 redis-rate-limiter.burstCapacity: 10 # bean,配置限流策略 key-resolver: '#{@ipKeyResolver}' - id: cloud-consumer-service uri: lb://cloud-consumer-service predicates: - Path=/consumer/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 5 redis-rate-limiter.burstCapacity: 10 key-resolver: '#{@ipKeyResolver}' # redis 配置 redis: host: localhost # 單機模式-host port: 6379 # 單機模式-端口 timeout: 3000 # 連接超時時間(毫秒) lettuce: # lettuce連接池 pool: max-active: 8 # 連接池最大連接數(使用負值表示沒有限制) max-wait: -1 # 連接池最大阻塞等待時間(使用負值表示沒有限制) max-idle: 8 # 連接池中的最大空閑連接 min-idle: 0 # 連接池中的最小空閑連接
3)、限(xian)流策略key-resolver配置(zhi):
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import reactor.core.publisher.Mono; import java.util.Objects; @Configuration public class RateLimitConfig { /** * 根據ip限(xian)流策略 * @return 限(xian)流策略 * */ @Bean @Primary // 設(she)置默認解析器(多個KeyResolver策略需指定) public KeyResolver ipKeyResolver() { return exchange -> // 獲取請求的遠程地址(zhi)(即客(ke)戶端IP地址(zhi)),并確保不為null Mono.just(Objects.requireNonNull(exchange.getRequest() // 獲取遠程地址(zhi)(InetSocketAddress) .getRemoteAddress()) // 獲取InetSocketAddress中的InetAddress對象 .getAddress() // 獲取(qu)客(ke)戶端的IP地址(以字符串(chuan)形(xing)式返回) .getHostAddress()); } /** * 根(gen)據uri路徑限流策(ce)(ce)略 * @return 限流策(ce)(ce)略 */ @Bean() public KeyResolver uriKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getURI().getPath()); } }
4)、自定(ding)義(yi)過濾(lv)器進(jin)行IP限流處理:
聲明Cache進行IP黑名(ming)單緩存:
import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.util.concurrent.TimeUnit; /** * IP 黑名單(dan)緩(huan)存 * * Guava CacheBuilder: * 一、核心優點 * 1、高性(xing)能本地訪問:微秒級響應(ying),適用(yong)于(yu)高頻讀取(qu)場景(如網關 IP 校驗) * 2、靈(ling)活過(guo)期策略:支持寫入后/訪問后雙維度自(zi)(zi)動(dong)過(guo)期 * 3、自(zi)(zi)動(dong)內存管理:基(ji)于(yu) LRU 的容量(liang)限制(maximumSize)防止 OOM * 4、細粒度并發控制:通過(guo) concurrencyLevel 優化鎖競爭(zheng) * 5、內置監控統計:通過(guo) cache.stats() 獲(huo)取(qu)命中率(lv)、淘汰次數(shu)等(deng)指(zhi)標(biao) * 二(er)、主要不足 * 1、單(dan)機局限性(xing):集群(qun)環境下數(shu)據不一致,需額外同(tong)步機制 * 2、內存容量(liang)受限:大流量(liang)場景易觸發頻繁淘汰或(huo) GC 壓力(li) * 3、無持久化能力(li):服(fu)務(wu)重(zhong)啟后數(shu)據丟失,需冷啟動(dong)預熱 * 4、緩(huan)存穿(chuan)透風險:未命中時可能穿(chuan)透到后端系統 */ public class IpBlackCache { public static final Cache<String, Boolean> IP_CACHE = CacheBuilder.newBuilder() // 最大cache數量 100條(tiao) .maximumSize(100) // 寫(xie)入后300s過期(qi) .expireAfterWrite(300, TimeUnit.SECONDS) // 不訪(fang)問 60s過(guo)期 .expireAfterAccess(60, TimeUnit.SECONDS) // 最多(duo)8個(ge)同(tong)時更(geng)新緩存的并發, 默認4 .concurrencyLevel(8) // 開啟cache統計 .recordStats() .build(); }
自(zi)定義過濾(lv)器進行IP限流(liu)處理:
import com.alibaba.fastjson.JSONObject; import com.iven.utils.IpBlackCache; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.HashMap; import java.util.Map; @Slf4j @Component public class GatewayIpRateLimiterFilter implements GlobalFilter, Ordered { /** * 過(guo)(guo)(guo)濾(lv)函數,用(yong)于(yu)處(chu)理(li)每個請(qing)求(qiu) * @param exchange 服務器(qi)(qi)web交(jiao)換對象,包含請(qing)求(qiu)和響應 * @param chain 網關過(guo)(guo)(guo)濾(lv)鏈,用(yong)于(yu)執行(xing)下一個過(guo)(guo)(guo)濾(lv)器(qi)(qi) * @return Mono<Void> 表示異步處(chu)理(li)完成 */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponse httpResponse = exchange.getResponse(); String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); // 檢查黑名單 Boolean ipCache = IpBlackCache.IP_CACHE.getIfPresent(ip); if (ipCache != null && ipCache) { //修改code為429,太多請求(qiu) httpResponse.setStatusCode(HttpStatus.TOO_MANY_REQUESTS); if (!httpResponse.getHeaders().containsKey("Content-Type")) { httpResponse.getHeaders().add("Content-Type", "application/json"); } Map<String, String> errorInfo = new HashMap<>(); errorInfo.put("code", HttpStatus.TOO_MANY_REQUESTS.toString()); errorInfo.put("msg", "訪問太(tai)頻繁"); String httpBody = JSONObject.toJSONString(errorInfo); log.info("該(gai)ip:{}已(yi)被拉入黑名單,錯誤(wu)信息{}", ip, httpBody); return httpResponse.writeWith(Flux.just(exchange.getResponse().bufferFactory().wrap(httpBody.getBytes()))); } // 采用默認(ren)令(ling)牌(pai)桶算(suan)法,如果觸發(fa)限流,返回(hui)HTTP響應狀態(tai)碼429 // 若需替換默認算法(如改用漏桶算法),實現(xian)RateLimiter接口,重寫isAllowed方法 return chain.filter(exchange).then(Mono.fromRunnable(() -> { // 檢查限流結果,將IP放入(ru)黑(hei)名單緩存中 if (httpResponse.getStatusCode() == HttpStatus.TOO_MANY_REQUESTS) { IpBlackCache.IP_CACHE.put(ip, true); } })); } /** * 獲(huo)取攔截器順序,使用最高級別,第一攔截 */ @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } }
擴展:自定義的(de)Redis令牌桶限流
@Component public class XxxRedisRateLimiter extends RedisRateLimiter { public Mono<Response> isAllowed(xxx) { xxx } }

3、重試過濾器:
|
一、重試過(guo)濾器(qi)的優(you)點: |
|
1、容錯性提(ti)升:自動處理瞬時故障(如網絡抖(dou)動、服(fu)務短時不(bu)可用)。 2、可用(yong)性(xing)增強:降低單次調(diao)用(yong)失敗對核(he)心流程的影響。 3、運維成本降低:減(jian)少人工介入,實現自動化(hua)恢復。 4、用戶(hu)體驗優化:通過后臺重試避免用戶(hu)感知到頻繁失敗(bai)。 |
|
二、重試機制的(de)核(he)心價值: |
|
1、應對分布(bu)式系統的(de)不(bu)可靠性:網絡和服務依(yi)賴(lai)的(de)故障(zhang)是常(chang)態,需容錯(cuo)機制保障(zhang)穩(wen)定性。 2、解(jie)決瞬時故(gu)障的普遍性:服務重(zhong)啟、資源(yuan)競爭等短暫問題可通過重(zhong)試快(kuai)速(su)恢(hui)復。 3、緩(huan)解(jie)依賴服務的波動性(xing):第三方服務或(huo)云(yun)基礎設施可能(neng)存在不穩(wen)定性(xing),重試提供緩(huan)沖。 4、強化系統魯棒性:在部分故(gu)障下維持核心功能,避免整體崩潰。 |
|
三、典型使用場景: |
|
1、HTTP/API調用:處(chu)理5xx服務端(duan)錯(cuo)誤或網絡超時。 2、數(shu)據庫操作:應對連接超(chao)時、死鎖等(deng)臨時異常(chang)。 3、消息隊列消費(fei):消息處理失敗后重試,確保最終一致性。 4、文(wen)件/資(zi)源訪問:臨時IO錯誤或資(zi)源鎖沖(chong)突的場景。 |
|
四、注意事項: |
|
1、避免無限重試:設(she)定(ding)最大重試次數(shu),防止雪(xue)崩效應。 2、區(qu)分錯(cuo)誤(wu)類型:僅對可恢復錯(cuo)誤(wu)(如5xx、超(chao)時)重(zhong)試(shi),非重(zhong)試(shi)錯(cuo)誤(wu)(如4xx)直接失敗。 3、退避策略:采用遞增延遲(如指數退避),緩解下(xia)游服務壓力。 4、監控與(yu)告(gao)警:記錄重(zhong)試日志(zhi),及(ji)時發現(xian)異常高頻重(zhong)試模(mo)式(shi)。 |
(1)、網關配置文件bootstrap-three.yml:
#重(zhong)(zhong)(zhong)試(shi)過(guo)濾器 # 設置重(zhong)(zhong)(zhong)試(shi)次數(shu):最多重(zhong)(zhong)(zhong)試(shi)3次。 # 狀(zhuang)(zhuang)態(tai)(tai)(tai)碼(ma)系(xi)列:當響(xiang)應的(de)(de)狀(zhuang)(zhuang)態(tai)(tai)(tai)碼(ma)屬于SERVER_ERROR系(xi)列(即5xx狀(zhuang)(zhuang)態(tai)(tai)(tai)碼(ma))時,會(hui)(hui)觸(chu)發重(zhong)(zhong)(zhong)試(shi)。 # 指定狀(zhuang)(zhuang)態(tai)(tai)(tai)碼(ma):當響(xiang)應的(de)(de)狀(zhuang)(zhuang)態(tai)(tai)(tai)碼(ma)為SERVICE_UNAVAILABLE(通常是503狀(zhuang)(zhuang)態(tai)(tai)(tai)碼(ma))時,也會(hui)(hui)觸(chu)發重(zhong)(zhong)(zhong)試(shi) # 對外暴(bao)露端口 server: port: 9090 spring: #項(xiang)目名 application: name: cloud-gateway-service cloud: nacos: config: server-addr: localhost:8848 file-extension: yaml # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # context-path: /nacos # username: nacos # password: nacos discovery: server-addr: localhost:8848 # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # username: nacos # password: nacos #############################網關配(pei)置########################### gateway: # 服(fu)務路(lu)(lu)由(you)配(pei)置(路(lu)(lu)由(you)是構建網關的(de)基本模塊,由(you)ID,目標URI,一系(xi)列(lie)的(de)斷言和過濾(lv)器組成) routes: # 路(lu)(lu)由(you)的(de)ID,沒有固定(ding)規則但要求唯(wei)一,建議(yi)配(pei)合服(fu)務名 - id: cloud-provider-service # 路由的地址,lb表示使(shi)(shi)用(yong)負(fu)載均衡(引入負(fu)載均衡依(yi)賴(lai))到微服(fu)務,也可以使(shi)(shi)用(yong)http正常轉發 # uri: lb://服務注冊(ce)(ce)中心注冊(ce)(ce)的(de)服務名稱(cheng) # uri: http://localhost:8080 uri: lb://cloud-provider-service #斷言(yan)工廠(chang)列(lie)表(biao): predicates: - Path=/provider/** filters: # 重試過濾器 - name: Retry args: # 重試次數 retries: 3 # 哪些段的狀態碼需要重試, 默認5xx series: - SERVER_ERROR # 指定哪些狀態需要重試 statuses: SERVICE_UNAVAILABLE - id: cloud-consumer-service uri: lb://cloud-consumer-service predicates: - Path=/consumer/** filters: - name: Retry args: retries: 3 series: - SERVER_ERROR statuses: SERVICE_UNAVAILABLE
(2)、相關測試接口:
/** * 重試(shi)過濾(lv)器測(ce)試(shi) * */ private int requestCount = 0; @GetMapping("/testRetry") public ResponseEntity<String> test() { requestCount++; System.out.println("生產者服務測(ce)試請(qing)求重試次數: " + requestCount); // 返回(hui)503狀態碼 return new ResponseEntity<>("Service Unavailable", HttpStatus.SERVICE_UNAVAILABLE); }

4、請求大小限制過濾器:
當客戶端(duan)請(qing)(qing)求體大小超過 maxSize 設定值時,網(wang)關會(hui)直接攔截請(qing)(qing)求,返(fan)回 HTTP 413 (Payload Too Large) 狀態碼(ma)
(1)、保障(zhang)系統穩定性(xing):攔截超大請(qing)求,防止內(nei)存(cun)溢(yi)出和服務崩潰
(2)、強化安全防(fang)護:阻斷DDoS攻(gong)擊,避免惡(e)意大流量沖擊后(hou)端
(3)、優(you)化網絡(luo)性能:降低無效帶寬消(xiao)耗,提升整體吞吐量
(4)、統一流(liu)量治理:標準(zhun)化異常響應格式,簡化客(ke)戶(hu)端(duan)錯誤處理邏輯
(1)、網關配置文件bootstrap-four.yml:
#請(qing)(qing)求大小限制過濾(lv)器(qi) # 當(dang)客戶端請(qing)(qing)求體(ti)大小超過 maxSize 設定值時(shi),網關(guan)會直接(jie)攔截請(qing)(qing)求,返回 HTTP 413 (Payload Too Large) 狀態碼。 # 單位換算 maxSize 以字節為(wei)單位,計算方式: 1MB = 1024 * 1024 = 1,048,576 bytes # Windows系統文件生成(PowerShell)0.9M文件:fsutil file createnew 0.9M.bin 900000 # Windows系(xi)統文件生成(PowerShell)1.1M文件:fsutil file createnew 1.1M.bin 1100000 # 對外暴露端口 server: port: 9090 spring: #項目名 application: name: cloud-gateway-service cloud: nacos: config: server-addr: localhost:8848 file-extension: yaml # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # context-path: /nacos # username: nacos # password: nacos discovery: server-addr: localhost:8848 # namespace: 3fd40f6b-0bc9-4a59-8838-0a64269125b4 # username: nacos # password: nacos #############################網關(guan)配置(zhi)########################### gateway: # 服務路(lu)由配置(zhi)(路(lu)由是構建網關(guan)的(de)基(ji)本模塊,由ID,目(mu)標(biao)URI,一系列的(de)斷言和過濾器(qi)組(zu)成) routes: # 路(lu)由的(de)ID,沒有固(gu)定規則但要求唯一,建議配合服務名 - id: cloud-provider-service # 路由的地址,lb表(biao)示(shi)使用(yong)負載均衡(heng)(引(yin)入負載均衡(heng)依賴)到微服務,也可(ke)以使用(yong)http正常轉發(fa) # uri: lb://服(fu)務注冊(ce)中心注冊(ce)的服(fu)務名稱 # uri: http://localhost:8080 uri: lb://cloud-provider-service #斷(duan)言工廠列(lie)表(biao): predicates: - Path=/provider/** filters: # 請求大小限制過濾器 - name: RequestSize args: # 單位字節:限制1M maxSize: 1000000 - id: cloud-consumer-service uri: lb://cloud-consumer-service predicates: - Path=/consumer/** filters: - name: RequestSize args: maxSize: 1000000
(2)、相關測試接口:
/** * 請求大小限制過濾器測(ce)試 * */ @PostMapping("/testRequestSize") public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) { // 網關會先攔截大文件請(qing)求,此處只需要處理通過網關的合(he)法請(qing)求 return ResponseEntity.ok().body(String.format("文(wen)件(jian)上傳(chuan)成功!文(wen)件(jian)名:%s,大小(xiao):%d 字節(jie)", file.getOriginalFilename(), file.getSize())); }
