LIM 监控系统支持JAVA_Spring Cloud Gateway 原生支持接口限流该怎么玩

关于pig:

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

关于 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如何实现多维度限流请参考我的博客

开始Gateway 限流

POM 依赖

org.springframework.cloud

spring-cloud-starter-gateway

org.springframework.boot

spring-boot-starter-data-redis-reactive

配置按照请求IP 的限流

spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: lb://pigx-upms

order: 10000

predicates:

- Path=/admin/**

filters:

- name: RequestRateLimiter

args:

redis-rate-limiter.replenishRate: 1 # 令牌桶的容积

redis-rate-limiter.burstCapacity: 3 # 流速 每秒

key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表达式去的对应的bean

- StripPrefix=1

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

/**

* 自定义限流标志的key,多个维度可以从这里入手

* exchange对象中获取服务ID、请求信息,用户信息等

*/

@Bean

KeyResolver remoteAddrKeyResolver() {

return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());

}

OK 完成。

压力测试

并发5个线程。

01ade6033915e29312d152dfc95f425e.png

Redis 数据变化

我们使用redis的monitor 命令,实时查看redis 的操作情况。

会发现在redis中会操作两个key

request_rate_limiter.{xxx}.timestamp

request_rate_limiter.{xxx}.tokens

08a2264834969513f5f1ba7f5eac4f2a.png

实现原理

dcd168c69e0ee5d114f20fea8a9e03c9.png

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

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

public Mono isAllowed(String routeId, String id) {

Config routeConfig = getConfig().getOrDefault(routeId, defaultConfig);

int replenishRate = routeConfig.getReplenishRate();

int burstCapacity = routeConfig.getBurstCapacity();

try {

List keys = getKeys(id);

returns unixtime in seconds.

List scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "",

Instant.now().getEpochSecond() + "", "1");

// 这里是核心,执行redis 的LUA 脚本。

Flux> flux =

this.redisTemplate.execute(this.script, keys, scriptArgs);

return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L)))

.reduce(new ArrayList(), (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 脚本

b989e82f48eaac3597baf3cac8cee75c.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值