1. 前言
微服务中用到了网关的话,自然而然就会考虑网关限流的问题;
当前项目中网关使用的是gateway,而它默认的限流是选择redis的方式来实现限流;
2. 限流方式
3. 项目引入gateway限流
- 引入依赖
<!--redis 用于实现gateway的限流-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
<!--如果父项目中限定了版本的话,这里不需要再具体制定-->
<version>2.1.3.RELEASE</version>
</dependency>
- springboot入口类中注入KeyResolver ,采用什么方式限流
@Slf4j
@EnableDiscoveryClient
@EnableCircuitBreaker
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GatewayApplication {
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext application = SpringApplication.run(GatewayApplication.class, args);
}
//注入bean
@Bean
public KeyResolver ipKeyResolver(){
return new KeyResolver() {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
/**
* 限流条件:
* 1.用户ip地址(桶是私有)
* 2.用户用户名(桶是私有)
* 3.微服的路径(桶是共享的)
*/
//此处根据用户的id做为条件限流
return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
};
}
}
- application.yml文件中配置
其实关键就是在filters中加入name,args的配置,可以对每个服务单独配置;
server:
port: 5550
spring:
profiles:
active: dev
application:
name: svc-gateway
redis: ## redis 用于网关限流
host: 192.168.226.128
timeout: 50000ms
cloud:
gateway:
locator:
enabled: true
routes:
- id: svc-user
uri: lb://SVC-USER
predicates:
- Path=/user/**
filters:
- StripPrefix=1
- name: RequestRateLimiter #请求数限流 名字不能随便写
args:
key-resolver: "#{@ipKeyResolver}"
redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
redis-rate-limiter.burstCapacity: 1 #令牌桶总容量
- id: svc-resources
uri: lb://SVC-RESOURCES
predicates:
- Path=/resources/**
filters:
- StripPrefix=1
- name: RequestRateLimiter #请求数限流 名字不能随便写
args:
key-resolver: "#{@ipKeyResolver}"
redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
redis-rate-limiter.burstCapacity: 1 #令牌桶总容量
到这里我们就配置好了,只需要启动项目就有限流效果了,测试的时候都设置为1,然后页面我们可以访问来看到限流效果;
但在这里用专业的工具Jmeter来测试会更加能显示限流的功能之强大和控制之精准!
4. 效果测试:
这里我直接贴效果图,如果想知道具体操作,可点击我的另一篇文章具体介绍Jmeter的操作,点击传送门;
测试1:
jmeter参数如下图:
意思是1秒钟启动10个线程去发起请求,只执行一次;
redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
redis-rate-limiter.burstCapacity: 5 #令牌桶总容量
桶容量为5个,1秒钟加入一个,那么理论上用已经设置好的jemter请求参数,那就是10个请求应该有6个成功才对;
绿色代表请求成功,红色是失败,很符合我们的预期
测试2:
jmeter参数如下图:
意思是3秒钟启动15个线程去发起请求,只执行一次;
redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
redis-rate-limiter.burstCapacity: 5 #令牌桶总容量
桶容量为5个,1秒钟加入1个,三秒钟就是3个,那么理论上,那就是15个请求应该有5+1*3=8个成功才对;
细数一下,结果正好是8个,我重复测试了多次,准确率十分地高!控制得相当精确!
5. 总结
springboot项目中集成任何东西都是三板斧;
1.引入依赖;2.导入bean;3.yml加入配置;
spring gateway加入限流也是依然是那么风轻云淡;
我不太确定的是这两个参数究竟根据哪些因素去设置会更加合理?
是项目并发量?那这个并发量不同时期如何评估呢?
是服务器cpu性能吗?还是其他种种…?
或许最好的方法就是根据实际情况进行调整了!
最后,如果看完对你有所帮助,不要吝啬关注 / 点赞 / 收藏哟,感谢感谢~