沈阳网站建设模块维护,海淀网站建设联系方式,中国企业500强搜索版,花都网站 建设信科网络文章目录 令牌桶算法原理Gateway中限流实现 网关除了请求路由、身份验证#xff0c;还有一个非常重要的作用#xff1a;请求限流。当系统面对高并发请求时#xff0c;为了减少对业务处理服务的压力#xff0c;需要在网关中对请求限流#xff0c;按照一定的速率放行请求。 … 文章目录 令牌桶算法原理Gateway中限流实现 网关除了请求路由、身份验证还有一个非常重要的作用请求限流。当系统面对高并发请求时为了减少对业务处理服务的压力需要在网关中对请求限流按照一定的速率放行请求。
常见的限流算法包括
计数器算法漏桶算法令牌桶算法
算法介绍: https://blog.csdn.net/u012441595/article/details/102483501 令牌桶算法原理
SpringGateway中采用的是令牌桶算法令牌桶算法原理
准备一个令牌桶有固定容量一般为服务并发上限按照固定速率生成令牌并存入令牌桶如果桶中令牌数达到上限就丢弃令牌。每次请求调用需要先获取令牌只有拿到令牌才继续执行否则选择选择等待或者直接拒绝。 Gateway中限流实现
SpringCloudGateway是采用令牌桶算法其令牌相关信息记录在redis中因此我们需要安装redis并引入Redis相关依赖。
1) 引入redis有关依赖
!--redis--
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis-reactive/artifactId
/dependency注意这里不是普通的redis依赖而是响应式的Redis依赖因为SpringGateway是基于WebFlux的响应式
2) 配置过滤条件key
Gateway会在Redis中记录令牌相关信息我们可以自己定义令牌桶的规则例如 给不同的请求URI路径设置不同令牌桶 给不同的登录用户设置不同令牌桶 给不同的请求IP地址设置不同令牌桶
Redis中的一个Key和Value对就是一个令牌桶。因此Key的生成规则就是桶的定义规则。SpringCloudGateway中key的生成规则定义在KeyResolver接口中
public interface KeyResolver {MonoString resolve(ServerWebExchange exchange);}这个接口中的方法返回值就是给令牌桶生成的key。API说明
Mono是一个单元素容器用来存放令牌桶的keyServerWebExchange上下文对象可以理解为ServletContext可以从中获取request、response、cookie等信息
比如上面的三种令牌桶规则生成key的方式如下 给不同的请求URI路径设置不同令牌桶示例代码 return Mono.just(exchange.getRequest().getURI().getPath());// 获取请求URI给不同的登录用户设置不同令牌桶 return exchange.getPrincipal().map(Principal::getName);// 获取用户给不同的请求IP地址设置不同令牌桶 return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());// 获取请求者IP这里我们选择最后一种使用IP地址的令牌桶key。
我们定义一个类配置一个 KeyResolve r的 Bean 实例
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
Component
public class PathKeyResolver implements KeyResolver {Overridepublic MonoString resolve(ServerWebExchange exchange) {return Mono.just(exchange.getRequest().getURI().getPath());// 获取请求URI}
}3) 配置桶参数
另外令牌桶的参数需要通过yaml文件来配置参数有2个 replenishRate每秒钟生成令牌的速率基本上就是每秒钟允许的最大请求数量 burstCapacity令牌桶的容量就是令牌桶中存放的最大的令牌的数量
完整配置如下
server:port: 10010 # 网关端口
spring:application:name: gateway # 服务名称redis:host: localhostcloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-server # 路由id自定义只要唯一即可# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址uri: lb://user-server# 路由的目标地址 lb就是负载均衡后面跟服务名称predicates: # 路由断言也就是判断请求是否符合路由规则的条件- Path/user/**- id: order-service # 路由id自定义只要唯一即可uri: lb://orderservice # 路由的目标地址 lb就是负载均衡后面跟服务名称predicates: # 路由断言也就是判断请求是否符合路由规则的条件- Path/order/**default-filters:- AddRequestHeadername,xiaoming- name: RequestRateLimiter #请求数限流 名字不能随便写args:key-resolver: #{ipKeyResolver} # 指定一个key生成器redis-rate-limiter.replenishRate: 2 # 生成令牌的速率redis-rate-limiter.burstCapacity: 4 # 桶的容量globalcors: # 全局的跨域处理........这里配置了一个过滤器RequestRateLimiter并设置了三个参数
key-resolver#{ipKeyResolver}是SpEL表达式写法是#{bean的名称}ipKeyResolver就是我们定义的Bean名称redis-rate-limiter.replenishRate每秒钟生成令牌的速率redis-rate-limiter.burstCapacity令牌桶的容量
这样的限流配置可以达成的效果
每一个IP地址每秒钟最多发起2次请求每秒钟超过2次请求则返回429的异常状态码
4) 测试
429代表请求次数过多触发限流了。