Gateway實(shí)現(xiàn)限流的一些常見方式
Gateway怎么實(shí)現(xiàn)限流的
在API網(wǎng)關(guān)(如Spring Cloud Gateway、Kong、Nginx等)中實(shí)現(xiàn)限流是為了控制服務(wù)請(qǐng)求的頻率,從而避免系統(tǒng)過載,確保穩(wěn)定性和可用性。限流可以通過多種策略實(shí)現(xiàn),常見的方法包括基于請(qǐng)求次數(shù)、時(shí)間窗口、IP地址等方式進(jìn)行限制。下面是 Spring Cloud Gateway 實(shí)現(xiàn)限流的一些常見方式:
1.基于請(qǐng)求次數(shù)的限流
這種方法通過限制單位時(shí)間內(nèi)的請(qǐng)求次數(shù)來防止過多的請(qǐng)求訪問服務(wù)。例如,限制每秒鐘只能處理最多100個(gè)請(qǐng)求。
- Spring Cloud Gateway實(shí)現(xiàn):Spring Cloud Gateway提供了內(nèi)置的限流功能,可以通過
RequestRateLimiter過濾器來實(shí)現(xiàn)基于請(qǐng)求次數(shù)的限流。 示例配置:
spring:
cloud:
gateway:
routes:
- id: rate_limiter_route
uri: http://example.com
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒鐘請(qǐng)求的數(shù)量
redis-rate-limiter.burstCapacity: 20 # 突發(fā)容量,即短時(shí)間內(nèi)允許的最大請(qǐng)求數(shù)replenishRate: 每秒鐘允許的請(qǐng)求數(shù)。burstCapacity: 突發(fā)容量,表示短時(shí)間內(nèi)可以處理的最大請(qǐng)求數(shù),超過該數(shù)的請(qǐng)求會(huì)被丟棄或拒絕。
2.基于令牌桶算法(Token Bucket)限流
令牌桶算法是一種平滑請(qǐng)求流量的算法,它通過固定的速率生成令牌并將其存放在桶中,請(qǐng)求到達(dá)時(shí)需要獲取令牌才能處理,如果令牌桶為空,則請(qǐng)求被拒絕。
Spring Cloud Gateway實(shí)現(xiàn):使用RequestRateLimiter實(shí)現(xiàn)基于令牌桶的限流。
示例配置:
spring:
cloud:
gateway:
routes:
- id: token_bucket_route
uri: http://example.com
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒生成的令牌數(shù)
redis-rate-limiter.burstCapacity: 20 # 令牌桶的容量這里的配置和上面的請(qǐng)求次數(shù)限制類似,但背后實(shí)現(xiàn)的是令牌桶算法。
3.基于IP限流
可以根據(jù)客戶端IP地址來限制每個(gè)IP的請(qǐng)求頻率,避免某個(gè)客戶端過度訪問服務(wù)。通常使用Redis來實(shí)現(xiàn)基于IP的限流。
示例配置(使用Redis):
spring:
cloud:
gateway:
routes:
- id: ip_rate_limiter_route
uri: http://example.com
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
redis-rate-limiter.keyResolver: "#{@ipKeyResolver}"在這個(gè)例子中,keyResolver 指定了如何基于客戶端 IP 地址來限流,可以自定義一個(gè)IP解析器ipKeyResolver,這樣每個(gè)IP的請(qǐng)求次數(shù)會(huì)被限制。
4.基于時(shí)間窗口的限流
時(shí)間窗口限流是按照固定的時(shí)間窗口(如每分鐘、每小時(shí)等)來限制請(qǐng)求的數(shù)量。通過時(shí)間窗口來控制單位時(shí)間內(nèi)的最大請(qǐng)求數(shù)。
示例配置:
spring:
cloud:
gateway:
routes:
- id: time_window_route
uri: http://example.com
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 5 # 每秒鐘請(qǐng)求的數(shù)量
redis-rate-limiter.burstCapacity: 10 # 突發(fā)容量
redis-rate-limiter.requestedTokens: 1 # 每次請(qǐng)求消耗的令牌數(shù)這種方式將請(qǐng)求限制在一定的時(shí)間窗口內(nèi),如果在窗口內(nèi)的請(qǐng)求數(shù)量超過限制,將拒絕額外的請(qǐng)求。
5.自定義限流策略
Spring Cloud Gateway 還允許通過自定義KeyResolver、RateLimiter等來實(shí)現(xiàn)更靈活的限流策略。例如,基于用戶的ID、API路徑等來做不同的限流策略。
自定義KeyResolver示例:
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
}這個(gè)例子通過客戶端IP地址進(jìn)行限流。
6.其他網(wǎng)關(guān)限流工具
除了Spring Cloud Gateway,其他網(wǎng)關(guān)如 Kong、Nginx 等也提供了豐富的限流功能:
- Kong使用插件機(jī)制實(shí)現(xiàn)限流,支持基于請(qǐng)求次數(shù)、IP、API Key等的限流。
- Nginx可以通過
limit_req和limit_conn模塊來進(jìn)行限流控制。
總結(jié)
在 Spring Cloud Gateway 中,常見的限流方式包括:
- 基于請(qǐng)求次數(shù)的限流(Rate Limiting)
- 基于令牌桶算法的限流(Token Bucket)
- 基于IP的限流
- 基于時(shí)間窗口的限流
可以通過RequestRateLimiter過濾器實(shí)現(xiàn)這些策略,結(jié)合 Redis 等存儲(chǔ)技術(shù)來共享和持久化限流狀態(tài)。在選擇限流策略時(shí),需要根據(jù)業(yè)務(wù)需求、流量模式、以及系統(tǒng)的負(fù)載能力來決定。
分析Gateway 限流代碼
@Component
public class RateLimitConfig {
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("token"));
}
@Bean
KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
@Bean
KeyResolver apiKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getPath().value());
}
@Primary
@Bean
KeyResolver appIpKeyResolver() {
return exchange -> {
Route route = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
return Mono.just(exchange.getRequest().getRemoteAddress().getHostName().concat(route.getUri().getHost()));
};
}
}這段代碼實(shí)現(xiàn)了Spring Cloud Gateway的限流配置,具體的實(shí)現(xiàn)通過不同的KeyResolver來為請(qǐng)求提供唯一的標(biāo)識(shí),用于區(qū)分不同的請(qǐng)求來源或策略。KeyResolver是限流的核心組成部分,它決定了限流的“鍵”(即每個(gè)請(qǐng)求的唯一標(biāo)識(shí)),從而確保不同的請(qǐng)求按照不同的規(guī)則被限流。
以下是對(duì)代碼的詳細(xì)分析:
1.KeyResolver的作用
KeyResolver 是 Spring Cloud Gateway 中限流機(jī)制的一部分,用來生成與請(qǐng)求相關(guān)的唯一“鍵”。在限流時(shí),基于這些“鍵”來計(jì)算每個(gè)限流單元(例如每個(gè)用戶、每個(gè)IP、每個(gè)API等)的請(qǐng)求次數(shù)。限流規(guī)則會(huì)依據(jù)這些鍵來進(jìn)行流量控制。
2.userKeyResolver
@Bean KeyResolver userKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("token")); }- 功能:該
KeyResolver基于請(qǐng)求的查詢參數(shù)token生成唯一的限流鍵。 - 應(yīng)用場(chǎng)景:當(dāng)客戶端使用
token參數(shù)(可能是API Key或用戶身份標(biāo)識(shí)符)時(shí),可以基于該token對(duì)每個(gè)用戶進(jìn)行限流。每個(gè)用戶(或每個(gè)token)的請(qǐng)求次數(shù)將被單獨(dú)計(jì)數(shù)。 - 具體實(shí)現(xiàn):從請(qǐng)求的查詢參數(shù)中獲取
token參數(shù)的第一個(gè)值。如果沒有這個(gè)參數(shù),返回null或空值會(huì)導(dǎo)致限流功能不生效。
3.ipKeyResolver
@Bean KeyResolver ipKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); }- 功能:該
KeyResolver基于客戶端的 IP 地址生成限流鍵。 - 應(yīng)用場(chǎng)景:當(dāng)需要限制每個(gè)IP地址的請(qǐng)求頻率時(shí),使用此
KeyResolver。例如,可以限制每個(gè)IP在一定時(shí)間窗口內(nèi)的請(qǐng)求次數(shù),從而避免單個(gè)IP的過多請(qǐng)求對(duì)系統(tǒng)造成壓力。 - 具體實(shí)現(xiàn):通過
exchange.getRequest().getRemoteAddress()獲取客戶端的遠(yuǎn)程IP地址,然后使用getHostName()獲取IP的主機(jī)名。理論上,getHostName()會(huì)嘗試解析IP地址為主機(jī)名,但在某些情況下,可能直接返回IP地址。
4.apiKeyResolver
@Bean KeyResolver apiKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getPath().value()); }- 功能:該
KeyResolver基于請(qǐng)求的API路徑生成唯一的限流鍵。 - 應(yīng)用場(chǎng)景:當(dāng)需要限制某個(gè)API路徑的請(qǐng)求頻率時(shí),使用此
KeyResolver。例如,限制/api/v1/login或/api/v1/register路徑的訪問頻率,可以防止某個(gè)特定API被過度訪問。 - 具體實(shí)現(xiàn):通過
exchange.getRequest().getPath().value()獲取請(qǐng)求的路徑。這個(gè)路徑通常是 URI 的路徑部分,如/api/v1/resource。
5.appIpKeyResolver
@Primary
@Bean KeyResolver appIpKeyResolver()
{
return exchange ->
{
Route route = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); return Mono.just(exchange.getRequest().getRemoteAddress().getHostName().concat(route.getUri().getHost()));
};
}- 功能:該
KeyResolver綜合了客戶端的 IP 地址和路由的 URI 來生成限流鍵。 - 應(yīng)用場(chǎng)景:當(dāng)希望根據(jù)客戶端 IP 和訪問的具體服務(wù)進(jìn)行限流時(shí),使用此
KeyResolver。例如,可以限制每個(gè)IP對(duì)特定API的訪問頻率。 - 具體實(shí)現(xiàn):
- 通過
exchange.getRequest().getRemoteAddress().getHostName()獲取客戶端的 IP 地址。 - 通過
exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR)獲取當(dāng)前請(qǐng)求的路由信息。 route.getUri().getHost()獲取請(qǐng)求目標(biāo)服務(wù)的主機(jī)名(或域名),并將其與客戶端IP拼接,作為限流的唯一鍵。- 使用
concat()方法將客戶端IP與目標(biāo)服務(wù)主機(jī)名合并為一個(gè)字符串,以保證限流的獨(dú)立性。
- 通過
6.@Primary注解
@Primary @Bean KeyResolver appIpKeyResolver()
{
...
}- 作用:在有多個(gè)相同類型的
@Bean時(shí),@Primary注解表示優(yōu)先使用該Bean。如果在其他地方有KeyResolver的注入需求,Spring 將默認(rèn)使用appIpKeyResolver()方法返回的實(shí)例。 - 場(chǎng)景:當(dāng)存在多個(gè)
KeyResolver時(shí),如果沒有明確指定使用哪個(gè)KeyResolver,Spring 會(huì)自動(dòng)選擇標(biāo)記為@Primary的那個(gè)。這里標(biāo)記了appIpKeyResolver為默認(rèn)的KeyResolver。
總結(jié)
這段代碼定義了多個(gè) KeyResolver,并為不同的限流策略提供了可選擇的實(shí)現(xiàn):
userKeyResolver:基于請(qǐng)求的token限流,適用于基于用戶或身份的限流。ipKeyResolver:基于客戶端 IP 地址限流,適用于限制每個(gè)IP的請(qǐng)求次數(shù)。apiKeyResolver:基于請(qǐng)求路徑限流,適用于限制某個(gè)特定API的訪問。appIpKeyResolver:基于客戶端 IP 地址和路由的 URI 組合限流,適用于更細(xì)粒度的限流需求,確保同一IP對(duì)不同API的請(qǐng)求可以獨(dú)立計(jì)數(shù)。
@Primary 注解確保 appIpKeyResolver 是默認(rèn)的限流鍵生成器,除非特別指定,否則會(huì)優(yōu)先使用它。
這些 KeyResolver 會(huì)與 RequestRateLimiter 等限流功能配合使用,從而在 API 網(wǎng)關(guān)層實(shí)現(xiàn)精細(xì)化的限流控制。
怎么沒有指定限流的量,每秒允許訪問的量
在這段代碼中,雖然定義了不同的 KeyResolver 來生成限流的標(biāo)識(shí)符(如 token、IP 或 API路徑),但確實(shí)沒有指定實(shí)際的限流規(guī)則(例如每秒允許的訪問量)。限流的具體控制是通過 Spring Cloud Gateway 的 RequestRateLimiter 過濾器來實(shí)現(xiàn)的,而這個(gè)過濾器是用來根據(jù)指定的規(guī)則對(duì)請(qǐng)求進(jìn)行限流的。
要實(shí)現(xiàn)每秒允許的訪問量,你需要配置 RequestRateLimiter 過濾器,并為它指定限流規(guī)則(如每秒最大訪問量和最大突發(fā)流量)。
完整的限流配置示例
首先,你需要?jiǎng)?chuàng)建一個(gè) RequestRateLimiter 過濾器,并在過濾器中配置限流策略。通常,你可以通過如下方式來配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.gateway.filter.ratelimit.RequestRateLimiter;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.config.GlobalFilterAutoConfiguration;
@Configuration
public class GatewayConfig {
@Bean
public RequestRateLimiter filter(KeyResolver keyResolver) {
// 配置限流:每秒最多允許 10 次請(qǐng)求,突發(fā)流量最多為 20 次
return new RequestRateLimiter()
.setRateLimiter(new MyRateLimiter(10, 20)) // 每秒 10 次請(qǐng)求,突發(fā)流量最多 20 次
.setKeyResolver(keyResolver); // 設(shè)置限流的 KeyResolver
}
// 自定義一個(gè)簡(jiǎn)單的 RateLimiter 實(shí)現(xiàn)類
public static class MyRateLimiter implements RateLimiter {
private final int replenishRate;
private final int burstCapacity;
public MyRateLimiter(int replenishRate, int burstCapacity) {
this.replenishRate = replenishRate;
this.burstCapacity = burstCapacity;
}
@Override
public boolean isAllowed(String key) {
// 此處實(shí)現(xiàn)你自己的限流邏輯,可以借助令牌桶算法、漏桶算法等
return true; // 只是示例,實(shí)際需要實(shí)現(xiàn)限流邏輯
}
// 配置每秒最大請(qǐng)求數(shù)(每秒 10 次)
public int getReplenishRate() {
return replenishRate;
}
// 配置突發(fā)容量
public int getBurstCapacity() {
return burstCapacity;
}
}
}如何將限流規(guī)則與KeyResolver配合?
在這段代碼中,RequestRateLimiter 的限流規(guī)則(如每秒允許 10 次請(qǐng)求,突發(fā)容量為 20)會(huì)與之前定義的 KeyResolver 配合,限制特定 token、IP 或 API 路徑的訪問頻率。
KeyResolver選擇:可以使用你之前定義的userKeyResolver、ipKeyResolver或apiKeyResolver來作為限流的依據(jù)。- 限流邏輯:通過
MyRateLimiter類實(shí)現(xiàn)限流邏輯(如令牌桶、漏桶等算法)。每個(gè)限流的“key”(例如token或IP)會(huì)根據(jù)配置的規(guī)則(如每秒 10 次、突發(fā)流量 20 次)進(jìn)行訪問次數(shù)的限制。
示例配置:按token限流
假設(shè)你想基于 token 進(jìn)行限流,你可以這樣配置:
@Bean
public RequestRateLimiter filter(KeyResolver userKeyResolver) {
return new RequestRateLimiter()
.setRateLimiter(new MyRateLimiter(10, 20)) // 每秒 10 次請(qǐng)求,突發(fā)流量最多 20 次
.setKeyResolver(userKeyResolver); // 使用之前定義的基于 token 的 KeyResolver
}限流的配置項(xiàng)
replenishRate:每秒允許的請(qǐng)求數(shù)。例如,10表示每秒最多可以處理 10 個(gè)請(qǐng)求。burstCapacity:突發(fā)容量,表示在短時(shí)間內(nèi)可以允許的最大請(qǐng)求數(shù)。例如,20表示最多允許瞬間訪問 20 次,但通常會(huì)平滑地恢復(fù)到正常的請(qǐng)求速率。KeyResolver:你已經(jīng)定義了多個(gè)KeyResolver,它們決定了限流的粒度。你可以按用戶(token)、IP 地址、路徑等來分別限流。
總結(jié)
這段代碼本身只是定義了限流的標(biāo)識(shí)符(通過 KeyResolver)。真正的限流控制需要通過 RequestRateLimiter 過濾器來實(shí)現(xiàn),并在其中指定限流的具體限制量(如每秒允許多少次請(qǐng)求)。你可以使用 replenishRate 和 burstCapacity 來配置每秒允許的訪問量及突發(fā)流量。
到此這篇關(guān)于Gateway實(shí)現(xiàn)限流的一些常見方式的文章就介紹到這了,更多相關(guān)Gateway限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring Cloud Gateway層限流實(shí)現(xiàn)過程
- SpringCloud Gateway的熔斷限流配置實(shí)現(xiàn)方法
- SpringCloud Gateway實(shí)現(xiàn)限流功能詳解
- SpringCloud?Gateway詳細(xì)分析實(shí)現(xiàn)負(fù)載均衡與熔斷和限流
- 深入學(xué)習(xí)spring cloud gateway 限流熔斷
- Spring Cloud Gateway不同頻率限流的解決方案(每分鐘,每小時(shí),每天)
- spring cloud gateway整合sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流
- spring cloud gateway 限流的實(shí)現(xiàn)與原理
- 詳解Spring Cloud Gateway 限流操作
相關(guān)文章
Java 集合框架之List 的使用(附小游戲練習(xí))
這篇文章主要介紹Java 集合框架中List 的使用,下面文章將圍繞Java 集合框架中List 的使用展開話題,并附上一些小游戲練習(xí),需要的朋友可以參考一下2021-10-10
Java傳入用戶名和密碼并自動(dòng)提交表單實(shí)現(xiàn)登錄到其他系統(tǒng)的實(shí)例代碼
這篇文章主要介紹了Java傳入用戶名和密碼并自動(dòng)提交表單實(shí)現(xiàn)登錄到其他系統(tǒng),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01
詳解Java 反射和反射的應(yīng)用場(chǎng)景
這篇文章主要介紹了Java 反射和反射的應(yīng)用場(chǎng)景的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java反射的相關(guān)知識(shí),感興趣的朋友可以了解下2020-08-08
詳解log4j-over-slf4j與slf4j-log4j12共存stack overflow異常分析
這篇文章主要介紹了詳解log4j-over-slf4j與slf4j-log4j12共存stack overflow異常分析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07
SpringBoot發(fā)送郵件功能 驗(yàn)證碼5分鐘過期
這篇文章主要為大家詳細(xì)介紹了SpringBoot發(fā)送郵件功能,驗(yàn)證碼5分鐘過期,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03
淺談HashMap、HashTable的key和value是否可為null
這篇文章主要介紹了淺談HashMap、HashTable的key和value是否可為null,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09

