Spring Cloud Gateway 原生的接口限流该怎么玩

关于pig:

基于Spring Cloud、oAuth2.0开发基于Vue前后分离的开发平台,支持账号、短信、SSO等多种登录,提供配套视频开发教程。

码云地址:https://gitee.com/log4j/pig

关于 Spring Cloud Gateway

SpringCloudGateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring云网关旨在提供一种简单而有效的路由API的方法。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。

zuul如何实现多维度限流请参考我的博客

Zuul:构建高可用网关之多维度限流

开始Gateway 限流

POM 依赖

1<!--spring cloud gateway依赖--> 2<dependency> 3 <groupId>org.springframework.cloud</groupId> 4 <artifactId>spring-cloud-starter-gateway</artifactId> 5</dependency> 6<!--基于 reactive stream 的redis --> 7<dependency> 8 <groupId>org.springframework.boot</groupId> 9 <artifactId>spring-boot-starter-data-redis-reactive</artifactId> 10</dependency>

配置按照请求IP 的限流

1spring: 2 cloud: 3 gateway: 4 routes: 5 - id: requestratelimiter_route 6 uri: lb://pigx-upms 7 order: 10000 8 predicates: 9 - Path=/admin/** 10 filters: 11 - name: RequestRateLimiter 12 args: 13 redis-rate-limiter.replenishRate: 1 # 令牌桶的容积 14 redis-rate-limiter.burstCapacity: 3 # 流速 每秒 15 key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表达式去的对应的bean 16 - StripPrefix=1

配置bean,多维度限流量的入口

1/** 2* 自定义限流标志的key,多个维度可以从这里入手 3* exchange对象中获取服务ID、请求信息,用户信息等 4*/ 5@Bean 6KeyResolver remoteAddrKeyResolver() { 7 return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); 8}

OK 完成。

压力测试

并发5个线程。
image

Redis 数据变化

我们使用redis的monitor 命令,实时查看redis 的操作情况。
会发现在redis中会操作两个key

  • request_rate_limiter.{xxx}.timestamp
  • request_rate_limiter.{xxx}.tokens image

实现原理

image

Spring Cloud Gateway 默认实现 Redis限流,如果扩展只需要实现ratelimter接口即可。

RedisRateLimter 的核心代码,判断是否取到令牌的实现,通过调用 redis的LUA 脚本。

1public Mono<Response> isAllowed(String routeId, String id) { 2 Config routeConfig = getConfig().getOrDefault(routeId, defaultConfig); 3 int replenishRate = routeConfig.getReplenishRate(); 4 int burstCapacity = routeConfig.getBurstCapacity(); 5 6 try { 7 List<String> keys = getKeys(id); 8 returns unixtime in seconds. 9 List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "", 10 Instant.now().getEpochSecond() + "", "1"); 11 // 这里是核心,执行redis 的LUA 脚本。 12 Flux<List<Long>> flux = 13 this.redisTemplate.execute(this.script, keys, scriptArgs); 14 return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L))) 15 .reduce(new ArrayList<Long>(), (longs, l) -> { 16 longs.addAll(l); 17 return longs; 18 }) .map(results -> { 19 boolean allowed = results.get(0) == 1L; 20 Long tokensLeft = results.get(1); 21 22 Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft)); 23 24 if (log.isDebugEnabled()) { 25 log.debug("response: " + response); 26 } 27 return response; 28 }); 29 } 30 catch (Exception e) { 31 log.error("Error determining if user allowed from redis", e); 32 } 33 return Mono.just(new Response(true, getHeaders(routeConfig, -1L))); 34}

LUA 脚本

image

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )