Spring Cloud Gateway限流实战
欢迎访问我的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中添加依赖org.springframework.boot:spring-boot-starter-data-redis-reactive
- 确定按照什么维度限流,例如按照请求中的username参数限流,这是通过编写KeyResolver接口的实现来完成的
- 配置application.yml文件,添加过滤器
- 以上就是使用RequestRateLimiter过滤器的套路了,简单么?接下来,咱们先编码再验证
源码下载
- 本篇实战中的完整源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
| 名称 | 链接 | 备注 |
|---|---|---|
| 项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
- 这个git项目中有多个文件夹,本篇的源码在spring-cloud-tutorials文件夹下,如下图红框所示:

- spring-cloud-tutorials文件夹下有多个子工程,本篇的代码是gateway-requestratelimiter,如下图红框所示:

准备工作
- 为了更好的演示Gateway的效果,在服务提供者provider-hello的代码(Hello.java)中新增一个web接口,可以接受一个入参:
@GetMapping("/userinfo")
public String userInfo(@RequestParam("username") String username) {
return Constants.HELLO_PREFIX + " " + username + ", " + dateStr();
}
- 后面的测试咱们就用上述接口;
编码
- 在父工程spring-cloud-tutorials之下新增子工程gateway-requestratelimiter,其pom.xml内容如下,重点是org.springframework.boot:spring-boot-starter-data-redis-reactive:
<?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,这里是根据请求参数username的值来限流的,假设真实请求中一半请求的username的等于Tom,另一半的username的等于Jerry,按照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);
}
}
- 代码写完了,接下来开始验证;
验证(桶容量等于入桶速度)
首先验证的是桶容量等于入桶速度时的效果,请修改gateway-requestratelimiter应用的application.yml中文件,使得redis-rate-limiter.replenishRate和redis-rate-limiter.burstCapacity的值都等于100,也就是说桶的大小等于100,每秒放入的令牌数也是100
确保redis已经启动,并且与application.yml中的配置保持一直
启动nacos(provider-hello依赖)
启动服务提供者provider-hello
启动gateway-requestratelimiter
为了模拟web请求,我这里使用了Apache Benchmark,windows版本的下载地址:
https://www.apachelounge.com/download/VS16/binaries/httpd-2.4.48-win64-VS16.zip上述文件下载解压后即可使用,在控制台进入Apache24\bin后执行以下命令,意思是向指定地址发送10000个请求,并发数为2:
ab -n 10000 -c 2 http://localhost:8081/hello/userinfo?username=Tom
- 控制台输出如下,可见不到八秒的时间,只成功了800个,证明限流符合预期:

验证(桶容量大于入桶速度)
接下来试试桶容量大于入桶速度时的限流效果,这对于我们控制峰值响应有很重要的参考价值
请修改gateway-requestratelimiter应用的application.yml中文件,redis-rate-limiter.replenishRate维持100不变,但是redis-rate-limiter.burstCapacity改成200,也就是说每秒放入的令牌数还是100,但桶的容量翻倍了
重启应用gateway-requestratelimiter
再次执行以下命令,意思是向指定地址发送10000个请求,并发数为2:
ab -n 10000 -c 2 http://localhost:8081/hello/userinfo?username=Tom
- 测试结果如下图,可见符合预期,可以将桶内令牌全部用掉,以支撑峰值超过QPS的场景:

验证(根据username的维度限流)
接下来验证限流的维度,究竟是不是按照请求参数username的值来限流的
咱们打开两个命令行,同时发送请求(动作要快),第一个的username等于Tom,第二个等于Jerry,理论上推测,如果都是8秒内完成,那么每个命令都有900个请求能成功
测试结果如下图,可见符合预期,每个username用的是自己的令牌:

- 至此,Spring Cloud Gateway限流实战已经完成,如此简单易用的限流方案,希望能给您的学习和使用带来参考
你不孤单,欣宸原创一路相伴
欢迎关注公众号:程序员欣宸
微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos
Spring Cloud Gateway限流实战的更多相关文章
- Spring Cloud 微服务五:Spring cloud gateway限流
前言:在互联网应用中,特别是电商,高并发的场景非常多,比如:秒杀.抢购.双11等,在开始时间点会使流量爆发式地涌入,如果对网络流量不加控制很有可能造成后台实例资源耗尽.限流是指通过指定的策略削减流量, ...
- 深入学习spring cloud gateway 限流熔断
前言 Spring Cloud Gateway 目前,Spring Cloud Gateway是仅次于Spring Cloud Netflix的第二个最受欢迎的Spring Cloud项目(就GitH ...
- spring cloud gateway 限流做法
标题 随风倒十分 反对法
- Spring Cloud Gateway自定义过滤器实战(观测断路器状态变化)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Spring Cloud Zuul 限流详解(附源码)(转)
在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. ...
- Spring Cloud(十二):Spring Cloud Zuul 限流详解(附源码)(转)
前面已经介绍了很多zuul的功能,本篇继续介绍它的另一大功能.在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选 ...
- spring cloud gateway 之限流篇
转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方 ...
- Spring Cloud Gateway 网关限流
Spring Cloud Gateway 限流 一.背景 二.实现功能 三.网关层限流 1.使用默认的redis来限流 1.引入jar包 2.编写配置文件 3.网关正常响应 4.网关限流响应 2.自定 ...
- spring cloud gateway整合sentinel作网关限流
说明: sentinel可以作为各微服务的限流,也可以作为gateway网关的限流组件. spring cloud gateway有限流功能,但此处用sentinel来作为替待. 说明:sentine ...
随机推荐
- JavaScript表单输入合法控制
写在前面 为了提高数据输入的容错性和数据库数据的安全性,除了后端对输入的数据的逻辑判断处理,还可以前端页面高效率处理,从而提高系统的可靠性,下面是这次项目中的自己写的一些符合当时需要的控制. 账号位数 ...
- Java(12)方法的重载
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201592.html 博客主页:https://www.cnblogs.com/testero ...
- /usr/bin/python^M: bad interpreter: No such file or directory
利用如下命令查看文件格式 :set ff 或 :set fileformat 可以看到如下信息 fileformat=dos 或 fileformat=unix 利用如下命令修改文件格式 :set f ...
- 51.N皇后问题
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案. 每一种解法包含一个明确的 n 皇后问题的棋 ...
- [敏捷软工团队博客]Beta阶段项目展示
团队成员简介和个人博客地址 头像 姓名 博客园名称 自我介绍 PM 测试 前端 后端 dzx 秃头院的大闸蟹 大闸蟹是1706菜市场里无菜可卖的底层水货.大闸蟹喜欢音乐(但可惜不会),喜欢lol(可惜 ...
- Beta阶段第二次会议
时间:2020.5.18 工作进展 姓名 工作 难度 完成度 ltx 1.在开小程序开发文档,学习相关知识 轻 85% xyq 1.完成活动场地申请可视化代码(耗时半天) 中 100% lm 1.设计 ...
- Spring父子上下文的使用案例
Spring父子上下文的使用案例 一.背景 二.需求 三.实现步骤 1.基础代码编写 2.测试结果 四.小彩蛋 五.完整代码 一.背景 最近在看在使用Spring Cloud的时候发现,当我们通过Fe ...
- 单片机STM32在开发中常用库函数详解
1.GPIO初始化函数 用法: voidGPIO_Configuration(void) { GPIO_InitTypeDefGPIO_InitStructure;//GPIO状态恢复默认参数 GPI ...
- 攻防世界 web1.view_source
右键不管用,F12打开控制台,直接查看flag.
- Linux修改bashrc
.bashrc是一个隐藏的文件,要打开并修改该文件需要: (1) 查看:ll -a 找到文件 .bashrc: (2) 打开:vi .bashrc (或者 vim .bashrc) 打开文件: (3) ...