Spring Cloud Gateway限流:基于Redis的請求限流實現

在這里插入圖片描述

文章目錄

    • 引言
    • 一、Spring Cloud Gateway限流基礎
      • 1.1 限流機制概述
      • 1.2 Redis分布式限流原理
    • 二、實現基于Redis的限流方案
      • 2.1 環境準備與依賴配置
      • 2.2 配置限流策略
      • 2.3 自定義限流響應
    • 三、高級應用與最佳實踐
      • 3.1 動態限流規則調整
      • 3.2 優先級與降級策略
      • 3.3 監控與告警
    • 總結

引言

在微服務架構中,API網關作為客戶端與后端服務之間的中間層,承擔著流量控制、安全防護和請求路由等重要職責。隨著業務規模的擴大,如何有效保護后端服務免受流量突增影響成為關鍵挑戰。Spring Cloud Gateway作為Spring生態系統中的新一代API網關,提供了強大的限流功能,特別是結合Redis實現的分布式限流方案,為構建高可用、高性能的微服務架構提供了堅實基礎。本文深入探討Spring Cloud Gateway基于Redis的請求限流實現,包括核心原理、配置方法和實踐優化。

一、Spring Cloud Gateway限流基礎

1.1 限流機制概述

Spring Cloud Gateway的限流功能基于令牌桶和漏桶算法實現,支持單機限流和分布式限流。令牌桶算法以恒定速率向桶中添加令牌,每個請求消耗一個令牌,當桶空時請求被拒絕,適合處理突發流量;漏桶算法則以固定速率處理請求,多余請求等待或拒絕,更適合穩定速率控制。Spring Cloud Gateway通過RequestRateLimiter過濾器工廠將這些算法與路由規則集成,提供靈活的限流配置。

/*** 限流過濾器工廠配置示例*/
@Configuration
public class RateLimiterConfig {/*** 配置基于Redis的限流過濾器工廠*/@Beanpublic RedisRateLimiter redisRateLimiter() {// 參數含義:replenishRate=每秒允許的請求數, burstCapacity=令牌桶容量return new RedisRateLimiter(5, 10);}/*** 自定義限流響應配置*/@Beanpublic KeyResolver ipKeyResolver() {// 使用請求IP作為限流鍵return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());}
}

1.2 Redis分布式限流原理

在分布式環境中,單機限流無法應對集群部署的情況。Spring Cloud Gateway集成了Redis實現分布式限流,核心實現是通過Redis的原子操作和Lua腳本保證在分布式環境下的計數一致性。當請求到達網關時,限流算法通過Redis檢查并更新令牌計數,實現跨多個網關實例的統一流量控制。這種方式確保了無論請求被路由到哪個網關實例,都能保持總體流量符合預設限制。

/*** Redis分布式限流的核心Lua腳本邏輯(簡化版)* Spring Cloud Gateway內部使用類似實現*/
// 這段代碼展示了Redis Lua腳本的核心邏輯
String luaScript = "local tokens_key = KEYS[1] " +"local timestamp_key = KEYS[2] " +"local rate = tonumber(ARGV[1]) " +"local capacity = tonumber(ARGV[2]) " +"local now = tonumber(ARGV[3]) " +"local requested = tonumber(ARGV[4]) " +"local fill_time = capacity/rate " +"local ttl = math.floor(fill_time*2) " +"local last_tokens = tonumber(redis.call('get', tokens_key)) " +"if last_tokens == nil then " +"  last_tokens = capacity " +"end " +"local last_refreshed = tonumber(redis.call('get', timestamp_key)) " +"if last_refreshed == nil then " +"  last_refreshed = 0 " +"end " +"local delta = math.max(0, now-last_refreshed) " +"local filled_tokens = math.min(capacity, last_tokens+(delta*rate)) " +"local allowed = filled_tokens >= requested " +"local new_tokens = filled_tokens " +"if allowed then " +"  new_tokens = filled_tokens - requested " +"end " +"redis.call('setex', tokens_key, ttl, new_tokens) " +"redis.call('setex', timestamp_key, ttl, now) " +"return { allowed, new_tokens }";

二、實現基于Redis的限流方案

2.1 環境準備與依賴配置

實現Redis限流首先需要引入相關依賴,包括Spring Cloud Gateway、Spring Data Redis和Spring Boot Actuator,后者提供了監控端點便于觀察限流情況。配置Redis連接信息后,需要啟用限流過濾器并定義限流鍵解析器,確定基于什么維度(IP、用戶ID或API路徑等)進行限流。

/*** Maven依賴配置*/
// pom.xml依賴配置
// <dependencies>
//     <!-- Spring Cloud Gateway -->
//     <dependency>
//         <groupId>org.springframework.cloud</groupId>
//         <artifactId>spring-cloud-starter-gateway</artifactId>
//     </dependency>
//     
//     <!-- Redis支持 -->
//     <dependency>
//         <groupId>org.springframework.boot</groupId>
//         <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
//     </dependency>
//     
//     <!-- 監控支持 -->
//     <dependency>
//         <groupId>org.springframework.boot</groupId>
//         <artifactId>spring-boot-starter-actuator</artifactId>
//     </dependency>
// </dependencies>/*** 應用配置示例*/
// application.yml基礎配置
// spring:
//   application:
//     name: api-gateway
//   redis:
//     host: localhost
//     port: 6379
//   cloud:
//     gateway:
//       routes:
//         - id: user-service
//           uri: lb://user-service
//           predicates:
//             - Path=/api/users/**
//           filters:
//             - name: RequestRateLimiter
//               args:
//                 redis-rate-limiter.replenishRate: 10
//                 redis-rate-limiter.burstCapacity: 20
//                 key-resolver: "#{@ipKeyResolver}"

2.2 配置限流策略

Spring Cloud Gateway支持多種限流策略配置方式,包括基于配置文件的聲明式配置和基于代碼的編程式配置。對于復雜場景,可以針對不同路由定義不同的限流規則,例如為重要API設置更高的訪問限制,為公共API設置較低限制。此外,還可以基于請求屬性(如請求方法、請求頭和查詢參數等)靈活調整限流規則。

/*** 多維度限流配置示例*/
@Configuration
public class RateLimiterConfiguration {/*** 基于IP地址的限流鍵解析器*/@Beanpublic KeyResolver ipKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());}/*** 基于用戶標識的限流鍵解析器*/@Beanpublic KeyResolver userKeyResolver() {return exchange -> Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst("X-User-Id")).defaultIfEmpty("anonymous");}/*** 基于API路徑的限流鍵解析器*/@Beanpublic KeyResolver apiPathKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getPath().value());}/*** 針對不同場景的組合限流鍵解析器*/@Beanpublic KeyResolver compositeKeyResolver() {return exchange -> {String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");String path = exchange.getRequest().getPath().value();// 組合用戶ID和API路徑作為限流鍵return Mono.just(String.format("%s:%s", userId != null ? userId : "anonymous", path));};}
}

2.3 自定義限流響應

當請求被限流時,默認情況下網關返回HTTP 429(Too Many Requests)狀態碼。為了提升用戶體驗,可以自定義限流響應,包括返回友好的錯誤信息、設置重試時間和提供備用資源鏈接等。通過實現GatewayFilterFactory,可以完全控制限流后的響應處理邏輯。

/*** 自定義限流響應處理*/
@Component
public class CustomRateLimiterGatewayFilterFactory extends RequestRateLimiterGatewayFilterFactory {private final RedisRateLimiter redisRateLimiter;public CustomRateLimiterGatewayFilterFactory(RedisRateLimiter redisRateLimiter) {super(redisRateLimiter);this.redisRateLimiter = redisRateLimiter;}@Overridepublic GatewayFilter apply(Config config) {KeyResolver keyResolver = getKeyResolver(config);return (exchange, chain) -> {Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);return keyResolver.resolve(exchange).flatMap(key -> redisRateLimiter.isAllowed(route.getId(), key)).flatMap(response -> {if (!response.isAllowed()) {// 請求被限流,返回自定義響應ServerHttpResponse serverResponse = exchange.getResponse();serverResponse.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);serverResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON);// 構建友好的錯誤信息Map<String, Object> errorResponse = new HashMap<>();errorResponse.put("code", 429);errorResponse.put("message", "請求頻率超限");errorResponse.put("timestamp", System.currentTimeMillis());// 添加限流信息errorResponse.put("allowed", response.getTokensRemaining());errorResponse.put("burst", redisRateLimiter.getBurstCapacity(route.getId()));// 添加重試建議long waitTime = response.getHeaders().getFirst("X-RateLimit-Reset") != null ?Long.parseLong(response.getHeaders().getFirst("X-RateLimit-Reset")) : 1000;errorResponse.put("retryAfter", waitTime);byte[] responseBody = null;try {responseBody = new ObjectMapper().writeValueAsBytes(errorResponse);} catch (JsonProcessingException e) {return Mono.error(e);}return serverResponse.writeWith(Mono.just(serverResponse.bufferFactory().wrap(responseBody)));}// 請求未被限流,添加限流信息到響應頭ServerHttpResponse originalResponse = exchange.getResponse();originalResponse.getHeaders().add("X-RateLimit-Remaining", String.valueOf(response.getTokensRemaining()));return chain.filter(exchange);});};}
}

三、高級應用與最佳實踐

3.1 動態限流規則調整

在實際業務場景中,限流規則通常需要根據業務波動、系統負載和用戶重要性等因素動態調整。Spring Cloud Gateway結合Spring Cloud Config或Nacos等配置中心,可以實現限流規則的動態更新,無需重啟服務。更進一步,結合監控系統可以實現自適應限流,根據系統負載自動調整限流閾值。

/*** 動態限流規則配置*/
@Configuration
@RefreshScope
public class DynamicRateLimiterConfig {@Value("${rate-limit.default-replenish-rate:10}")private int defaultReplenishRate;@Value("${rate-limit.default-burst-capacity:20}")private int defaultBurstCapacity;@Bean@RefreshScopepublic RedisRateLimiter redisRateLimiter() {return new RedisRateLimiter(defaultReplenishRate, defaultBurstCapacity);}/*** 路由級別限流配置*/@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route("user_service", r -> r.path("/api/users/**").filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()).setKeyResolver(userKeyResolver()))).uri("lb://user-service")).route("order_service", r -> r.path("/api/orders/**").filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(orderRateLimiter()).setKeyResolver(apiPathKeyResolver()))).uri("lb://order-service")).build();}/*** 訂單服務專用限流器*/@Bean@RefreshScopepublic RedisRateLimiter orderRateLimiter() {// 為訂單服務配置更嚴格的限流規則return new RedisRateLimiter(5, 10);}
}

3.2 優先級與降級策略

在高負載場景下,除了限流外,還可以結合優先級策略和降級機制提升系統韌性。優先級策略確保重要請求(如付款、訂單)優先處理;降級策略則在系統超載時提供備用服務或簡化功能。Spring Cloud Gateway可以與Sentinel、Resilience4j等熔斷降級框架集成,構建更完善的流量治理方案。

/*** 優先級與降級配置*/
@Configuration
public class ResilienceConfig {/*** 基于用戶等級的優先級限流*/@Beanpublic KeyResolver userTierKeyResolver() {return exchange -> {// 獲取用戶等級String userTier = exchange.getRequest().getHeaders().getFirst("X-User-Tier");// 為不同用戶等級設置不同的限流鍵前綴,從而應用不同的限流策略if ("premium".equals(userTier)) {return Mono.just("premium:" + exchange.getRequest().getPath().value());} else if ("standard".equals(userTier)) {return Mono.just("standard:" + exchange.getRequest().getPath().value());} else {return Mono.just("basic:" + exchange.getRequest().getPath().value());}};}/*** 服務降級邏輯*/@Beanpublic RouterFunction<ServerResponse> fallbackRoute() {return RouterFunctions.route().GET("/fallback", request -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Map.of("message", "服務暫時不可用,請稍后再試"))).build();}/*** 整合限流與熔斷的路由配置*/@Beanpublic RouteLocator resilientRoutes(RouteLocatorBuilder builder) {return builder.routes().route("payment_service", r -> r.path("/api/payments/**").filters(f -> f// 配置限流.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()).setKeyResolver(userTierKeyResolver()))// 配置熔斷.circuitBreaker(c -> c.setName("paymentCircuitBreaker").setFallbackUri("forward:/fallback"))// 配置超時.setResponseTimeout(Duration.ofSeconds(3))).uri("lb://payment-service")).build();}
}

3.3 監控與告警

有效的限流系統離不開完善的監控和告警機制。Spring Boot Actuator提供了限流指標的監控端點,可以與Prometheus、Grafana等監控系統集成,實時觀察限流情況。通過設置合理的告警閾值,當限流頻率超過預期時及時通知運維人員,防止系統長時間處于限流狀態影響用戶體驗。

/*** 限流監控配置*/
@Configuration
public class RateLimitMonitoringConfig {/*** 自定義限流指標收集*/@Beanpublic MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {return registry -> registry.config().commonTags("application", "api-gateway");}/*** 限流事件監聽器*/@Componentpublic class RateLimitEventListener {private final Counter rateLimitCounter;private final Counter rejectedRequestCounter;public RateLimitEventListener(MeterRegistry registry) {this.rateLimitCounter = registry.counter("gateway.ratelimit.count");this.rejectedRequestCounter = registry.counter("gateway.ratelimit.rejected");}@EventListenerpublic void onRateLimitEvent(RequestRateLimiterEvent event) {rateLimitCounter.increment();if (!event.isAllowed()) {rejectedRequestCounter.increment();// 記錄被限流的詳細信息log.warn("Rate limited request: key={}, routeId={}", event.getKey(), event.getRouteId());// 檢查限流頻率,超過閾值時觸發告警double rejectRate = rejectedRequestCounter.count() / rateLimitCounter.count();if (rejectRate > 0.2) {  // 拒絕率超過20%時告警sendAlert(event.getRouteId(), rejectRate);}}}private void sendAlert(String routeId, double rejectRate) {// 實現告警邏輯,如發送郵件、短信或調用告警APIlog.error("High rate limit rejection detected: routeId={}, rejectRate={}",routeId, rejectRate);}}
}

總結

Spring Cloud Gateway基于Redis的限流實現為微服務架構提供了強大的流量控制能力。通過令牌桶算法和Redis分布式協調,它能夠在集群環境下提供一致的限流體驗。本文介紹了限流的基本原理、配置方法和自定義擴展,同時探討了動態限流規則、優先級策略和監控告警等高級應用。在實際開發中,合理利用這些特性可以構建出更具韌性的API網關,有效保護后端服務免受流量突增影響,提高系統整體可用性。隨著微服務架構的不斷演進,Spring Cloud Gateway的限流功能將繼續發揮重要作用,幫助開發者構建更加健壯的分布式系統。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903381.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903381.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903381.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

keil修改字體無效,修改字體為“微軟雅黑”方法

在網上下載了微軟雅黑字體&#xff0c;微軟雅黑參考下載鏈接 結果在Edit->Configuration中找不到這個字體 這個時候可以在keil的安裝目錄中找到UV4/global.prop文件 用記事本打開它進行編輯&#xff0c;把字體名字改成微軟雅黑 重新打開keil就發現字體成功修改了。 這個…

CSS文字特效實例:猜猜我是誰

CSS文字特效實例&#xff1a;猜猜我是誰 引言 在之前的文章中&#xff0c;我們分別實現了空心文字、文字填充、文字模糊、文字裂開等效果。本文將使用一個小實例&#xff0c;組合使用相關特效&#xff1a;當鼠標懸停在圖片上時&#xff0c;其余圖片模糊&#xff0c;且文字會上…

美團社招一面

美團社招一面 做題 1、面試題 <style> .outer{width: 100px;background: red;height: 100px; }.inner {width: 50px;height: 50px;background: green; }</style> <div class"outer"><div class"inner"></div> </div>…

InitializingBean接口和@PostConstruct-筆記

1. InitializingBean 簡介 1.1 功能簡介 InitializingBean 是 Spring 框架中的一個接口&#xff0c;用在 Bean 初始化后執行自定義邏輯。它提供了 afterPropertiesSet() 方法&#xff0c;該方法在以下時機被 Spring 容器自動調用&#xff1a; 屬性注入完成后&#xff08;即所…

《代碼整潔之道》第9章 單元測試 - 筆記

測試驅動開發 (TDD) 是一種編寫整潔代碼的“規程”或“方法論”&#xff0c;而不僅僅是測試技術。 JaCoCo 在運行測試后生成詳細的覆蓋率報告的工具&#xff0c; maven 引用。 測試驅動開發 測試驅動開發&#xff08;TDD&#xff09;是什么&#xff1f; TDD 不是說寫完代碼…

openGauss新特性 | DataKit支持PostgreSQL到openGauss的遷移能力

Postgresql-\>openGauss遷移工具debezium-connector-postgres 可獲得性 本特性自openGauss 7.0.0-RC1版本開始引入。 特性簡介 debezium-connector-postgres工具是一個基于Java語言的Postgresql到openGauss的復制工具。該工具提供了初始全量數據及對象&#xff08;視圖、…

在MySQL Shell里 重啟MySQL 8.4實例

前一段時間看到MySQL官方視頻的Oracle工程師在mysql shell里面重啟mysql實例&#xff0c;感覺這個操作很方便&#xff0c;所以來試試&#xff0c;下面為該工程師的操作截圖 1.MySQL Shell 通過root用戶連上mysql&#xff0c;shutdown mysql實例 [rootmysql8_3 bin]# mysqlshMy…

truffle

文章目錄 truffle目錄結構各文件作用在本地測試合約 truffle 項目來自https://github.com/Dapp-Learning-DAO/Dapp-Learning/blob/main/basic/04-web3js-truffle/README-CN.md Truffle 是基于 Solidity 語言的一套開發框架&#xff0c;它簡化了去中心化應用&#xff08;Dapp&…

SpringCloud核心組件Eureka菜鳥教程

關于Spring Cloud Eureka的核心概念 Eureka 是 Netflix 開源的一款基于 REST 的服務發現工具&#xff0c;主要用于中間層服務器的云端負載均衡。它通過維護一個服務注冊表來實現服務之間的通信1。在 Spring Cloud 中&#xff0c;Eureka 提供了一個高可用的服務注冊與發現機制&a…

職業教育新形態數字教材的建設與應用:重構教育生態的數字化革命

教育部新時代職業學校名師(名匠)名校長培養計劃專題 四川省第四批職業學校名師(名匠)培養計劃專題 在某職業院校的智能制造課堂上&#xff0c;學生佩戴VR設備&#xff0c;通過數字教材中的虛擬工廠完成設備裝配訓練&#xff0c;系統實時生成操作評分與改進建議。這一場景折射出…

基于Python的攜程國際機票價格抓取與分析

一、項目背景與目標 攜程作為中國領先的在線旅行服務平臺&#xff0c;提供了豐富的機票預訂服務。其國際機票價格受多種因素影響&#xff0c;包括季節、節假日、航班時刻等。通過抓取攜程國際機票價格數據&#xff0c;我們可以進行價格趨勢分析、性價比評估以及旅行規劃建議等…

Windows 圖形顯示驅動開發-初始化WDDM 1.2 和 PnP

(WDDM) 1.2 及更高版本顯示微型端口驅動程序的所有 Windows 顯示驅動程序都必須支持以下行為&#xff0c;以響應即插即用 (PnP) 基礎結構啟動和停止請求。 根據驅動程序返回成功或失敗代碼&#xff0c;或者系統硬件是基于基本輸入/輸出系統 (BIOS) 還是統一可擴展固件接口 (UEF…

【1區SCI】Fusion entropy融合熵,多尺度,復合多尺度、時移多尺度、層次 + 故障識別、診斷-matlab代碼

引言 2024年9月&#xff0c;研究者在數學領域國際頂級SCI期刊《Chaos, Solitons & Fractals》&#xff08;JCR 1區&#xff0c;中科院1區 Top&#xff09;上以“Fusion entropy and its spatial post-multiscale version: Methodology and application”為題發表最新科學研…

高并發架構設計之緩存

一、引言 緩存技術作為高并發架構設計的基石之一&#xff0c;通過數據暫存和快速訪問機制&#xff0c;在提升系統性能、降低后端負載方面發揮著不可替代的作用。優秀的緩存設計能夠將系統吞吐量提升數個數量級&#xff0c;將響應時間從秒級降至毫秒級&#xff0c;甚至成為系統…

Unity AI-使用Ollama本地大語言模型運行框架運行本地Deepseek等模型實現聊天對話(一)

一、Ollama介紹 官方網頁&#xff1a;Ollama官方網址 中文文檔參考&#xff1a;Ollama中文文檔 相關教程&#xff1a;Ollama教程 Ollama 是一個開源的工具&#xff0c;旨在簡化大型語言模型&#xff08;LLM&#xff09;在本地計算機上的運行和管理。它允許用戶無需復雜的配置…

Docker Python 鏡像使用指南

1. 使用 Python 鏡像創建容器 docker run -itd -v /data:/data python:latest 作用&#xff1a;創建一個基于 python:latest 鏡像的容器&#xff0c;并后臺運行。 參數說明&#xff1a; -itd&#xff1a;交互式后臺運行&#xff08;-i 交互模式&#xff0c;-t 分配偽終端&…

matlab中Simscape的調用-入門

Simscape 是由 MathWorks 公司開發的一款基于物理建模的仿真工具&#xff0c;它建立在 MATLAB/Simulink 平臺之上&#xff0c;專門用于建模和仿真多領域物理系統。 主要特點 多領域建模&#xff1a;Simscape 提供了豐富的物理元件庫&#xff0c;涵蓋了機械、電氣、液壓、氣動…

Flowable7.x學習筆記(十三)查看部署流程圖

前言 Flowable 的流程圖是 Flowable Modeler 或 Process Editor 中&#xff0c;使用拖拽和屬性面板基于 BPMN 2.0 元素&#xff08;如任務、網關、事件、序列流等&#xff09;渲染出的業務流程圖形界面?。 一、將圖形導出可查看的作用 ① 可視化建模 幫助業務分析師和開發者…

Bootstrap 模態框

Bootstrap 模態框 Bootstrap 模態框&#xff08;Modal&#xff09;是 Bootstrap 框架中的一個組件&#xff0c;它允許你在一個頁面中創建一個模態對話框&#xff0c;用于顯示內容、表單、圖像或其他信息。模態框通常覆蓋在當前頁面上&#xff0c;提供了一種不離開當前頁面的交…

python-69-基于graphviz可視化軟件生成流程圖

文章目錄 1 Graphviz可視化軟件1.1 graphviz簡介1.2 安裝部署2 基于python示例應用2.1 基本示例2.2 解決中文顯示亂碼2.3 顯示多個輸出邊2.4 顯示輸出引腳名稱2.5 從左至右顯示布局2.6 設置節點為方形3 參考附錄1 Graphviz可視化軟件 1.1 graphviz簡介 Graphviz(Graph Visua…