Spring Cloud Gateway 网关限流
Spring Cloud Gateway 限流
一、背景
在我们平时开发过程中,一般一个请求都是需要经过多个微服务的,**比如:**请求从A服务流过B服务,如果A服务请求过快,导致B服务响应慢,那么必然会导致系统出现问题。因为,我们就需要有限流操作。
二、实现功能
提供自定义的限流key生成,需要实现
KeyResolver
接口。提供默认的限流算法,实现实现
RateLimiter
接口。当限流的key为空时,直接不限流,放行,由参数
spring.cloud.gateway.routes[x].filters[x].args[x].deny-empty-key
来控制限流时返回客户端的相应码有
spring.cloud.gateway.routes[x].filters[x].args[x].status-code
来控制,需要写这个org.springframework.http.HttpStatus
类的枚举值。RequestRateLimiter
只能使用name || args
这种方式来配置,不能使用简写的方式来配置。
RequestRateLimiter
过滤器的redis-rate-limiter
参数是在RedisRateLimiter
的CONFIGURATION_PROPERTY_NAME
属性配置的。构造方法中用到了。
三、网关层限流
限流的key 生成规则,默认是 PrincipalNameKeyResolver
来实现
限流算法,默认是 RedisRateLimiter
来实现,是令牌桶算法。
1、使用默认的redis来限流
在Spring Cloud Gateway
中默认提供了 RequestRateLimiter
过滤器来实现限流操作。
1、引入jar包
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2、编写配置文件
spring:
application:
name: gateway-9205
cloud:
nacos:
discovery:
server-addr: localhost:8847
gateway:
routes:
- id: user-provider-9206
uri: lb://user-provider-9206
predicates:
- Path=/user/**
filters:
- RewritePath=/user(?<segment>/?.*), $\{segment}
- name: RequestRateLimiter
args:
# 如果返回的key是空的话,则不进行限流
deny-empty-key: false
# 每秒产生多少个令牌
redis-rate-limiter.replenishRate: 1
# 1秒内最大的令牌,即在1s内可以允许的突发流程,设置为0,表示阻止所有的请求
redis-rate-limiter.burstCapacity: 1
# 每次请求申请几个令牌
redis-rate-limiter.requestedTokens: 1
redis:
host: 192.168.7.1
database: 12
port: 6379
password: 123456
server:
port: 9205
debug: true
3、网关正常响应
4、网关限流响应
2、自定义限流算法和限流key
1、自定义限流key
编写一个类实现 KeyResolver 接口即可。
package com.huan.study.gateway;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Optional;
/**
* 限流的key获取
*
* @author huan.fu 2021/9/7 - 上午10:25
*/
@Slf4j
@Component
public class DefaultGatewayKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
// 获取当前路由
Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
ServerHttpRequest request = exchange.getRequest();
String uri = request.getURI().getPath();
log.info("当前返回的uri:[{}]", uri);
return Mono.just(Optional.ofNullable(route).map(Route::getId).orElse("") + "/" + uri);
}
}
配置文件中的写法(部分)
spring:
cloud:
gateway:
routes:
- id: user-provider-9206
filters:
- name: RequestRateLimiter
args:
# 返回限流的key
key-resolver: "#{@defaultGatewayKeyResolver}"
2、自定义限流算法
编写一个类实现 RateLimiter ,此处使用内存限流
package com.huan.study.gateway;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.RateLimiter;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter;
import org.springframework.cloud.gateway.support.ConfigurationService;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
/**
* @author huan.fu 2021/9/7 - 上午10:36
*/
@Component
@Slf4j
@Primary
public class DefaultGatewayRateLimiter extends AbstractRateLimiter<DefaultGatewayRateLimiter.Config> {
/**
* 和配置文件中的配置属性相对应
*/
private static final String CONFIGURATION_PROPERTY_NAME = "default-gateway-rate-limiter";
private RateLimiter rateLimiter = RateLimiter.create(1);
protected DefaultGatewayRateLimiter(ConfigurationService configurationService) {
super(DefaultGatewayRateLimiter.Config.class, CONFIGURATION_PROPERTY_NAME, configurationService);
}
@Override
public Mono<Response> isAllowed(String routeId, String id) {
log.info("网关默认的限流 routeId:[{}],id:[{}]", routeId, id);
Config config = getConfig().get(routeId);
return Mono.fromSupplier(() -> {
boolean acquire = rateLimiter.tryAcquire(config.requestedTokens);
if (acquire) {
return new Response(true, Maps.newHashMap());
} else {
return new Response(false, Maps.newHashMap());
}
});
}
@Getter
@Setter
@ToString
public static class Config {
/**
* 每次请求多少个 token
*/
private Integer requestedTokens;
}
}
配置文件中的写法(部分)
spring:
cloud:
gateway:
routes:
- id: user-provider-9206
filters:
- name: RequestRateLimiter
args:
# 自定义限流规则
rate-limiter: "#{@defaultGatewayRateLimiter}"
注意️:
这个类需要加上 @Primary
注解。
3、配置文件中的写法
spring:
application:
name: gateway-9205
cloud:
nacos:
discovery:
server-addr: localhost:8847
gateway:
routes:
- id: user-provider-9206
uri: lb://user-provider-9206
predicates:
- Path=/user/**
filters:
- RewritePath=/user(?<segment>/?.*), $\{segment}
- name: RequestRateLimiter
args:
# 自定义限流规则
rate-limiter: "#{@defaultGatewayRateLimiter}"
# 返回限流的key
key-resolver: "#{@defaultGatewayKeyResolver}"
# 如果返回的key是空的话,则不进行限流
deny-empty-key: false
# 限流后向客户端返回的响应码429,请求太多
status-code: TOO_MANY_REQUESTS
# 每次请求申请几个令牌 default-gateway-rate-limiter 的值是在 defaultGatewayRateLimiter 中定义的。
default-gateway-rate-limiter.requestedTokens: 1
server:
port: 9205
debug: true
四、完成代码
https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway-redis-limiter
五、参考文档
1、https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-redis-ratelimiter
Spring Cloud Gateway 网关限流的更多相关文章
- 微服务架构spring cloud - gateway网关限流
1.算法 在高并发的应用中,限流是一个绕不开的话题.限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池.线程池). ...
- spring cloud gateway 之限流篇
转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方 ...
- spring boot gateway自定义限流
参考:https://blog.csdn.net/ErickPang/article/details/84680132 采用自带默认网关请参照微服务架构spring cloud - gateway网关 ...
- Spring Cloud gateway 网关服务二 断言、过滤器
微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...
- Spring Cloud gateway 网关四 动态路由
微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...
- Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制
一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...
- .net core下,Ocelot网关与Spring Cloud Gateway网关的对比测试
有感于 myzony 发布的 针对 Ocelot 网关的性能测试 ,并且公司下一步也需要对.net和java的应用做一定的整合,于是对Ocelot网关.Spring Cloud Gateway网关做个 ...
- Spring Cloud gateway 网关服务 一
之前我们介绍了 zuul网关服务,今天聊聊spring cloud gateway 作为spring cloud的亲儿子网关服务.很多的想法都是参照zuul,为了考虑zuul 迁移到gateway 提 ...
- 从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析
API 网关 API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题 ...
随机推荐
- Docker Compose 实践及梳理
Docker Compose 可以实现 Docker 容器集群的编排,可以通过 docker-compose.yml 文件,定义我们的服务及其需要的依赖,轻松地运行在测试.生产等环境 文档 Produ ...
- J2EE分布式微服务云开发架构 Spring Cloud+Mybatis+ElementUI 前后端分离J2EE分布式微服务云开发架构 Spring Cloud+Mybatis+ElementUI 前后端分离
鸿鹄云架构[系统管理平台]是一个大型企业.分布式.微服务.云架构的JavaEE体系快速研发平台,基于模块化.微服务化.原子化.热部署的设计思想,使用成熟领先的无商业限制的主流开源技术(Spring ...
- 使用IntelliJ工具打包kotlin为bat文件运行报错 Exception in thread "main" java.lang.NoClassDefFoundError
Exception in thread "main" java.lang.NoClassDefFoundError 这个很有可能是因为idea里的java版本与电脑上的java环境 ...
- dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标
大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...
- HCNP Routing&Switching之路由控制-策略路由
前文我们了解了路由策略工具Route-Policy相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15322135.html:今天我们来聊一聊策略路由相 ...
- Ubuntu18.04安装jenkins
官网参考指引:https://pkg.jenkins.io/debian-stable/ wget -q -O - https://pkg.jenkins.io/debian-stable/jenki ...
- PHP 流行的框架
Aura Laravel Symphony Yii Zend php components Packagist 最好的组件: Awesome PHP https://www.yiiframework. ...
- session与cookie的联系与区别
一.Session与Cookie介绍 这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你 ...
- P5404-[CTS2019]重复【KMP,dp】
正题 题目链接:https://www.luogu.com.cn/problem/P5404 题目大意 给出一个字符串\(S\),然后求有多少个长度为\(m\)的串\(T\)满足.无限多个串\(T\) ...
- Visual Studio Code (VSCode) 配置 C/C++ 开发编译环境
前言 工作多年,突然发现很多C++的基础都忘记了,加之C++不断更新换代后的各种新特性,于是想重拾C++的基础学习.虽然现在工作都是Linux平台,但考虑到个人方便,自己也仅仅想重温语法,家里家外都可 ...