SpringCloud系列之網(wǎng)關(guān)gateway-14.網(wǎng)關(guān)層的其他妙用 - 限流

網(wǎng)關(guān)限流三步走

這里采用令牌桶計(jì)數(shù)的方式做限流,總共分三步

準(zhǔn)備工作

我們的Best Practice是基于Redis來實(shí)現(xiàn)限流,因此要保證本地啟動了Redis服務(wù)让虐。同時(shí)將下列配置加入到Gateway的配置文件中:

spring:
  application:
    name: gateway-service
redis:
    host: localhost
    port: 6379
    database: 0

這里是配置Redis連接信息的孽文,假如你不配置的話,Gateway也會嘗試用默認(rèn)配置項(xiàng)來連接Redis真友。但如果你在Redis配置信息中提供了錯誤的IP或者Port的話,調(diào)用方法時(shí)依然會成功紧帕,不過限流功能就失效了锻狗,因?yàn)榈讓拥腘etty服務(wù)無法連接到Redis,也就無法提供限流支持。但Gateway為了保證服務(wù)可用性轻纪,限流功能的異常并不會阻礙正常的方法調(diào)用油额。

Key Resolver

Gateway的限流組件要求定義一個(gè)Key Resolver用來對每次路由請求生成一個(gè)Key,這個(gè)Key就是一個(gè)限流分組的標(biāo)識刻帚,每個(gè)Key相當(dāng)于一個(gè)令牌桶潦嘶。假如我們限定了一個(gè)服務(wù)每秒只能被調(diào)用3次,這個(gè)限制會對不同的Key單獨(dú)計(jì)數(shù)崇众,我們把調(diào)用方機(jī)器的Host Name作為限流Key掂僵,那么來自同一臺機(jī)器的調(diào)用將落到同一個(gè)Key下面,也就是說在這個(gè)場景下顷歌,每臺機(jī)器都獨(dú)立計(jì)算單位時(shí)間調(diào)用量锰蓬。
創(chuàng)建Key Resolver的方式很簡單:

@Bean
public KeyResolver remoteAddrKeyResolver() {
    return exchange -> Mono.just(
          exchange.getRequest().getRemoteAddress().getHostName());
}

上面的例子創(chuàng)建了基于Host Name的令牌生成器,我們可以根據(jù)自己的業(yè)務(wù)來選擇合適的Key眯漩,比如說可以在接口層面做限流(使用接口的Path作為Key)芹扭,還可以從Request中提取業(yè)務(wù)字段作為Key(比如用戶ID等)。

配置過濾器

spring:
    cloud:
        gateway:
            routes:
                - id:  feignapi
                uri: lb://FEIGN-SERVICE-PROVIDER
predicates:
- Path=/feign-api/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
key-resolver: '#{@remoteAddrKeyResolver}'
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20

在上面的限流配置中赦抖,我們主要關(guān)注最后3行中的屬性:
? key-resolver:這里注入的就是在上一步中我們定義的Key Resolver舱卡,它使用SpEL表達(dá)式從Spring上下文中獲取指定Bean
? replenishRate:令牌桶每秒的平均填充速度
? burstCapacity:令牌桶總量

java中如何配置網(wǎng)關(guān)限流


@Configuration
public class RedisLimiterConfiguration {

    @Bean
    @Primary
    public KeyResolver remoteAddrKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }

    @Bean
    @Primary
    public RedisRateLimiter redisRateLimiterUser() {
        return new RedisRateLimiter(1,2);
    }


}

@Configuration
public class GatewayConfiguration {

    @Autowired
    private TimerFilter timerFilter;

    @Autowired
    private KeyResolver remoteAddrKeyResolver;

    @Autowired
    private RedisRateLimiter redisRateLimiter;

    @Bean
    @Order
    public RouteLocator customizedRoutes(RouteLocatorBuilder routeLocatorBuilder){
        return routeLocatorBuilder.routes()
                .route(r->r.path("/java/**")
                        .and().method(HttpMethod.GET)
                        .filters(f->f.stripPrefix(1)
                                .requestRateLimiter(c->{
                                    c.setKeyResolver(remoteAddrKeyResolver);
                                    c.setRateLimiter(redisRateLimiter);
                                    c.setStatusCode(HttpStatus.BAD_GATEWAY);
                                })
                        )
                        .uri("lb://feign-client")
                )
                .route(r->r.path("/seckill/**")
                        .and().after(ZonedDateTime.now().plusMinutes(1))
                        .filters(f->f.stripPrefix(1))
                        .uri("lb://feign-client")
                )
                .build();
    }

}

小細(xì)節(jié)

假如我們不想依賴Redis的話,還有其他選擇方案嗎队萤?必須有轮锥,但是要靠大家自己動動手。如果大家想借助其他存儲介質(zhì)實(shí)現(xiàn)限流要尔,可以參考RedisRateLimiter這個(gè)類的實(shí)現(xiàn)舍杜,通過繼承AbstractRateLimiter來創(chuàng)建一個(gè)自定義的計(jì)數(shù)器。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赵辕,一起剝皮案震驚了整個(gè)濱河市既绩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌匆帚,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旁钧,死亡現(xiàn)場離奇詭異吸重,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)歪今,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門嚎幸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寄猩,你說我怎么就攤上這事嫉晶。” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵替废,是天一觀的道長箍铭。 經(jīng)常有香客問我,道長椎镣,這世上最難降的妖魔是什么诈火? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮状答,結(jié)果婚禮上冷守,老公的妹妹穿的比我還像新娘。我一直安慰自己惊科,他們只是感情好拍摇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馆截,像睡著了一般充活。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上孙咪,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天堪唐,我揣著相機(jī)與錄音,去河邊找鬼翎蹈。 笑死淮菠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荤堪。 我是一名探鬼主播合陵,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼澄阳!你這毒婦竟也來了拥知?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤碎赢,失蹤者是張志新(化名)和其女友劉穎低剔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肮塞,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡襟齿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枕赵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猜欺。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拷窜,靈堂內(nèi)的尸體忽然破棺而出开皿,到底是詐尸還是另有隱情涧黄,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布赋荆,位于F島的核電站笋妥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏糠睡。R本人自食惡果不足惜挽鞠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狈孔。 院中可真熱鬧信认,春花似錦、人聲如沸均抽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽油挥。三九已至潦蝇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間深寥,已是汗流浹背攘乒。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惋鹅,地道東北人则酝。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像闰集,于是被迫代替她去往敵國和親沽讹。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容