共计 5572 个字符,预计需要花费 14 分钟才能阅读完成。
欢送拜访我的 GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,波及 Java、Docker、Kubernetes、DevOPS 等;
本篇概览
- 本文是《Spring Cloud Gateway 实战》系列的第八篇,通过后面的学习,咱们对过滤器已理解得差不多,明天来补全过滤器的最初一个版块:限流(RequestRateLimiter)
- 默认的限流器是基于 redis 实现的,限流算法是大家相熟的令牌桶(Token Bucket Algorithm), 对于令牌捅的原理就不在此开展了,聪慧的您看一眼下图应该就懂了:装令牌的桶容量无限,例如最多 20 个,令牌进入桶的速度恒定(留神,这里是和漏桶算法的区别),例如每秒 10 个,底部每个申请能拿到令牌才会被解决:
RequestRateLimiter 根本套路
- 应用 RequestRateLimiter 过滤器的步骤非常简单:
- 筹备可用的 redis
- maven 或者 gradle 中增加依赖 <font color=”blue”>org.springframework.boot:spring-boot-starter-data-redis-reactive</font>
- 确定依照什么维度限流,例如依照申请中的 username 参数限流,这是通过编写 KeyResolver 接口的实现来实现的
- 配置 application.yml 文件,增加过滤器
- 以上就是应用 RequestRateLimiter 过滤器的套路了,简略么?接下来,咱们先编码再验证
源码下载
- 本篇实战中的残缺源码可在 GitHub 下载到,地址和链接信息如下表所示 (https://github.com/zq2599/blo…):
名称 | 链接 | 备注 |
---|---|---|
我的项目主页 | https://github.com/zq2599/blo… | 该我的项目在 GitHub 上的主页 |
git 仓库地址 (https) | https://github.com/zq2599/blo… | 该我的项目源码的仓库地址,https 协定 |
git 仓库地址 (ssh) | git@github.com:zq2599/blog_demos.git | 该我的项目源码的仓库地址,ssh 协定 |
- 这个 git 我的项目中有多个文件夹,本篇的源码在 <font color=”blue”>spring-cloud-tutorials</font> 文件夹下,如下图红框所示:
- <font color=”blue”>spring-cloud-tutorials</font> 文件夹下有多个子工程,本篇的代码是 <font color=”red”>gateway-requestratelimiter</font>,如下图红框所示:
筹备工作
- 为了更好的演示 Gateway 的成果,在服务提供者 <font color=”blue”>provider-hello</font> 的代码(Hello.java)中新增一个 web 接口,能够承受一个入参:
@GetMapping("/userinfo") | |
public String userInfo(@RequestParam("username") String username) {return Constants.HELLO_PREFIX + "" + username +", " + dateStr(); | |
} |
- 前面的测试咱们就用上述接口;
编码
- 在父工程 <font color=”blue”>spring-cloud-tutorials</font> 之下新增子工程 <font color=”red”>gateway-requestratelimiter</font>,其 pom.xml 内容如下,重点是 <font color=”blue”>org.springframework.boot:spring-boot-starter-data-redis-reactive</font>:
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<parent> | |
<artifactId>spring-cloud-tutorials</artifactId> | |
<groupId>com.bolingcavalry</groupId> | |
<version>1.0-SNAPSHOT</version> | |
</parent> | |
<modelVersion>4.0.0</modelVersion> | |
<artifactId>gateway-requestratelimiter</artifactId> | |
<dependencies> | |
<dependency> | |
<groupId>com.bolingcavalry</groupId> | |
<artifactId>common</artifactId> | |
<version>${project.version}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.cloud</groupId> | |
<artifactId>spring-cloud-starter-gateway</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-data-redis-reactive</artifactId> | |
</dependency> | |
</dependencies> | |
</project> |
- 配置文件 application.yml,请留神 RequestRateLimiter 的几个参数,曾经用中文增加了具体的正文:
server: | |
#服务端口 | |
port: 8081 | |
spring: | |
application: | |
name: circuitbreaker-gateway | |
# redis 配置 | |
redis: | |
host: 192.168.50.43 | |
port: 6379 | |
cloud: | |
gateway: | |
routes: | |
- id: path_route | |
uri: http://127.0.0.1:8082 | |
predicates: | |
- Path=/hello/** | |
filters: | |
- name: RequestRateLimiter | |
args: | |
# 令牌入桶的速度为每秒 100 个,相当于 QPS | |
redis-rate-limiter.replenishRate: 100 | |
# 桶内能装 200 个令牌,相当于峰值,要留神的是:第一秒从桶内能去 200 个,然而第二秒只能取到 100 个了,因为入桶速度是每秒 100 个 | |
redis-rate-limiter.burstCapacity: 200 | |
# 每个申请须要的令牌数 | |
redis-rate-limiter.requestedTokens: 1 |
- 指定限流维度的代码 CustomizeConfig.java,这里是依据申请参数 <font color=”blue”>username</font> 的值来限流的,假如实在申请中一半申请的 username 的等于 <font color=”red”>Tom</font>,另一半的 username 的等于 <font color=”red”>Jerry</font>,依照 application.yml 的配置,Tom 的申请 QPS 为 10,Jerry 的 QPS 也是 10:
package com.bolingcavalry.gateway.config; | |
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import reactor.core.publisher.Mono; | |
import java.util.Objects; | |
@Configuration | |
public class CustomizeConfig { | |
@Bean | |
KeyResolver userKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username")); | |
} | |
} |
- 毫无养分的启动类 RequestRateLimiterApplication.java:
package com.bolingcavalry.gateway; | |
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
@SpringBootApplication | |
public class RequestRateLimiterApplication {public static void main(String[] args) {SpringApplication.run(RequestRateLimiterApplication.class,args); | |
} | |
} |
- 代码写完了,接下来开始验证;
验证(桶容量等于入桶速度)
- 首先验证的是桶容量等于入桶速度时的成果,请批改 <font color=”blue”>gateway-requestratelimiter</font> 利用的 application.yml 中文件,使得 redis-rate-limiter.replenishRate 和 redis-rate-limiter.burstCapacity 的值都等于 100,也就是说桶的大小等于 100,每秒放入的令牌数也是 100
- 确保 redis 曾经启动,并且与 application.yml 中的配置放弃始终
- 启动 nacos(provider-hello 依赖)
- 启动服务提供者 <font color=”blue”>provider-hello</font>
- 启动 <font color=”blue”>gateway-requestratelimiter</font>
- 为了模仿 web 申请,我这里应用了 <font color=”blue”>Apache Benchmark</font>,windows 版本的下载地址:
https://www.apachelounge.com/… - 上述文件下载解压后即可应用,在控制台进入 <font color=”blue”>Apache24\bin</font> 后执行以下命令,意思是向指定地址发送 10000 个申请,并发数为 2:
ab -n 10000 -c 2 http://localhost:8081/hello/userinfo?username=Tom
- 控制台输入如下,可见不到八秒的工夫,只胜利了 800 个,证实限流合乎预期:
验证(桶容量大于入桶速度)
- 接下来试试桶容量大于入桶速度时的限流成果,这对于咱们管制峰值响应有很重要的参考价值
- 请批改 <font color=”blue”>gateway-requestratelimiter</font> 利用的 application.yml 中文件,redis-rate-limiter.replenishRate 维持 <font color=”blue”>100</font> 不变,然而 redis-rate-limiter.burstCapacity 改成 <font color=”red”>200</font>,也就是说每秒放入的令牌数还是 100,但桶的容量翻倍了
- 重启利用 <font color=”blue”>gateway-requestratelimiter</font>
- 再次执行以下命令,意思是向指定地址发送 10000 个申请,并发数为 2:
ab -n 10000 -c 2 http://localhost:8081/hello/userinfo?username=Tom
- 测试后果如下图,可见合乎预期,能够将桶内令牌全副用掉,以撑持峰值超过 QPS 的场景:
验证(依据 username 的维度限流)
- 接下来验证限流的维度,到底是不是依照申请参数 username 的值来限流的
- 咱们关上两个命令行,同时发送申请(动作要快),第一个的 username 等于 <font color=”blue”>Tom</font>,第二个等于 <font color=”blue”>Jerry</font>,实践上揣测,如果都是 8 秒内实现,那么每个命令都有 900 个申请能胜利
- 测试后果如下图,可见合乎预期,每个 username 用的是本人的令牌:
- 至此,Spring Cloud Gateway 限流实战曾经实现,如此简略易用的限流计划,心愿能给您的学习和应用带来参考
你不孤独,欣宸原创一路相伴
- Java 系列
- Spring 系列
- Docker 系列
- kubernetes 系列
- 数据库 + 中间件系列
- DevOps 系列
欢送关注公众号:程序员欣宸
微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游 Java 世界 …
https://github.com/zq2599/blog_demos
正文完