目录
一、限流算法
1、计数器算法
2、漏桶算法
3、令牌桶算法
二、Gateway中的限流
计数器算法是指从第一个请求开始,每多一个请求就加1,假设设置每秒限流100,当在一秒钟前500ms已经达到100,后面的500ms中的所有请求都会被拒绝。后面500ms的请求被拒绝掉这种现象称为“突刺现象”
漏桶算法可以解决“突刺现象”。就是跟生活中漏桶一样,一个水桶,下面有个洞往外漏水,会控制水流速度,不论水桶中有多少睡,漏水的速率保持一致。但是当水到达水桶上限,这时候就不行了。主要是当某时间段有大量请求,但是已经达到漏桶上限的情况。
令牌桶算法是对漏桶算法的一种改进。就是在桶中放入令牌,请求获取到令牌后才能继续执行,如果桶中没有令牌,请求要么继续等待,要么直接拒绝。
因为令牌是按照一定的速率放置到桶中,所以可以一定程度上解决突发访问。
SpringCloudGateWay项目参考:SpringCloudGateway--自动路由映射与手动路由映射_雨欲语的博客-CSDN博客
注意需要添加redis依赖包:
org.springframework.boot spring-boot-starter-data-redis
算法工厂由代码提供,令牌桶由redis提供,底层逻辑是lua脚本提供,已经封装好的。
限流实现方式主要是实现KeyResolver类,重写里面的resolve方法:
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 MyKeyResolver implements KeyResolver {@Overridepublic Mono resolve(ServerWebExchange exchange) {String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();return Mono.just(hostAddress);}
}
其中just方法参数表示根据什么限流,这里我使用的是根据ip地址进行限流。
配置文件:
server:port: 9999
spring:application:name: service-gatewaycloud: # 配置Spring Cloud相关属性gateway:discovery: # 配置网关发现机制locator: # 配置处理机制enabled: false # 开启网关自动映射处理逻辑lower-case-service-id: true # 开启小写转换filter:secure-headers:disable:- strict-transport-security- x-download-optionsroutes: # 配置网关中的一个完整路由,包括命名,地址,谓词集合(规则),过滤器集合- id: service-one # 路由定义的命名,唯一即可。命名规则符合Java中的变量符命名规则uri: lb://service-one # 当前路由定义对应的微服务转发地址,lb - 代表loadbalancepredicates: # 配置谓词集合- Path=/service/** filters:- name: RequestRateLimiterargs:keyResolver: '#{@myKeyResolver}' #使用springEL表达式,从spring容器中找对象,并赋值。'#{@beanName}'redis-rate-limiter.replenishRate: 1 #生产令牌速度,每秒多少个令牌redis-rate-limiter.burstCapacity: 5 # 令牌桶容量metadata:connect-timeout: 15000 #msresponse-timeout: 15000 #msnacos:username: nacospassword: nacosdiscovery:server-addr: 127.0.0.1group: devnamespace: devmetadata:version: v1.0.0redis:database: 0host: ${127.0.0.1}port: ${6379}password:lettuce:pool:max-active: 80max-idle: 80min-idle: 1max-wait: 5000time-between-eviction-runs: 1mshutdown-timeout: 10000mstimeout: 15000ms
启动前我们查看redis,keys *:
可以发现里面此时没有令牌。
启动项目,然后使用jmeter发送请求测试,这里我配置的每秒生产5个令牌,在jmeter中每秒发送10个请求:
其中失败的请求会返回Too Many Requests,redis查看令牌,可以看到其中本地的ip地址127.0.0.1:
下一篇:Httpclient测试