gateway限流之令牌桶算法RateLimiter

1. 前言

微服务中用到了网关的话,自然而然就会考虑网关限流的问题;
当前项目中网关使用的是gateway,而它默认的限流是选择redis的方式来实现限流;

2. 限流方式

3. 项目引入gateway限流

  1. 引入依赖
        <!--redis 用于实现gateway的限流-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
             <!--如果父项目中限定了版本的话,这里不需要再具体制定-->
            <version>2.1.3.RELEASE</version>   
        </dependency>
  1. 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());
            }
        };
    }

}
  1. 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性能吗?还是其他种种…?
或许最好的方法就是根据实际情况进行调整了!

最后,如果看完对你有所帮助,不要吝啬关注 / 点赞 / 收藏哟,感谢感谢~

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值