javascript
Spring Cloud Gateway 原生支持接口限流该怎么玩
關(guān)于pig:
基于Spring Cloud、oAuth2.0開發(fā)基于Vue前后分離的開發(fā)平臺,支持賬號、短信、SSO等多種登錄,提供配套視頻開發(fā)教程。
關(guān)于 Spring Cloud Gateway
SpringCloudGateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技術(shù)開發(fā)的網(wǎng)關(guān),Spring云網(wǎng)關(guān)旨在提供一種簡單而有效的路由API的方法。Spring Cloud Gateway作為Spring Cloud生態(tài)系中的網(wǎng)關(guān),目標(biāo)是替代Netflix ZUUL,其不僅提供統(tǒng)一的路由方式,并且基于Filter鏈的方式提供了網(wǎng)關(guān)基本的功能,例如:安全,監(jiān)控/埋點(diǎn),和限流等。
zuul如何實(shí)現(xiàn)多維度限流請參考我的博客
[Zuul:構(gòu)建高可用網(wǎng)關(guān)之多維度限流]
開始Gateway 限流
POM 依賴
<!--spring cloud gateway依賴--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--基于 reactive stream 的redis --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency>配置按照請求IP 的限流
spring:cloud:gateway:routes:- id: requestratelimiter_routeuri: lb://pigx-upmsorder: 10000predicates:- Path=/admin/**filters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 1 # 令牌桶的容積redis-rate-limiter.burstCapacity: 3 # 流速 每秒key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表達(dá)式去的對應(yīng)的bean- StripPrefix=1配置bean,多維度限流量的入口
/** * 自定義限流標(biāo)志的key,多個維度可以從這里入手 * exchange對象中獲取服務(wù)ID、請求信息,用戶信息等 */ @Bean KeyResolver remoteAddrKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); }OK 完成。
壓力測試
并發(fā)5個線程。
Redis 數(shù)據(jù)變化
我們使用redis的monitor 命令,實(shí)時(shí)查看redis 的操作情況。
會發(fā)現(xiàn)在redis中會操作兩個key
- request_rate_limiter.{xxx}.timestamp
- request_rate_limiter.{xxx}.tokens
實(shí)現(xiàn)原理
Spring Cloud Gateway 默認(rèn)實(shí)現(xiàn) Redis限流,如果擴(kuò)展只需要實(shí)現(xiàn)ratelimter接口即可。
RedisRateLimter 的核心代碼,判斷是否取到令牌的實(shí)現(xiàn),通過調(diào)用 redis的LUA 腳本。
public Mono<Response> isAllowed(String routeId, String id) {Config routeConfig = getConfig().getOrDefault(routeId, defaultConfig);int replenishRate = routeConfig.getReplenishRate();int burstCapacity = routeConfig.getBurstCapacity();try {List<String> keys = getKeys(id);returns unixtime in seconds.List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "",Instant.now().getEpochSecond() + "", "1");// 這里是核心,執(zhí)行redis 的LUA 腳本。Flux<List<Long>> flux =this.redisTemplate.execute(this.script, keys, scriptArgs);return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L))).reduce(new ArrayList<Long>(), (longs, l) -> {longs.addAll(l);return longs;}) .map(results -> {boolean allowed = results.get(0) == 1L;Long tokensLeft = results.get(1);Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft));if (log.isDebugEnabled()) {log.debug("response: " + response);}return response;});}catch (Exception e) {log.error("Error determining if user allowed from redis", e);}return Mono.just(new Response(true, getHeaders(routeConfig, -1L))); }LUA 腳本
總結(jié)
以上是生活随笔為你收集整理的Spring Cloud Gateway 原生支持接口限流该怎么玩的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 简单json和对象相互转换
- 下一篇: Unexpected end of JS