博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud Gateway 原生支持接口限流该怎么玩
阅读量:5952 次
发布时间:2019-06-19

本文共 2812 字,大约阅读时间需要 9 分钟。

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

[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、请求信息,用户信息等*/@BeanKeyResolver remoteAddrKeyResolver() {    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}

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 脚本。

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 脚本

image

转载地址:http://tgsxx.baihongyu.com/

你可能感兴趣的文章
密码概述
查看>>
jQuery的技巧01
查看>>
基于泛型实现的ibatis通用分页查询
查看>>
gopacket 使用
查看>>
AlertDialog对话框
查看>>
我的友情链接
查看>>
linux安全---cacti+ntop监控
查看>>
鸟哥的linux私房菜-shell简单学习-1
查看>>
nagios配置监控的一些思路和工作流程
查看>>
通讯组基本管理任务三
查看>>
Centos下基于Hadoop安装Spark(分布式)
查看>>
3D地图的定时高亮和点击事件(基于echarts)
查看>>
mysql开启binlog
查看>>
设置Eclipse编码方式
查看>>
分布式系统唯一ID生成方案汇总【转】
查看>>
并查集hdu1232
查看>>
Mysql 监视工具
查看>>
从前后端分离到GraphQL,携程如何用Node实现?\n
查看>>
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
nginc+memcache
查看>>