gateway限流之令牌桶算法

1. 前言

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

2. 限流方式

3. 项目引入gateway限流

1.引入依赖

    

    org.springframework.boot
    spring-boot-starter-data-redis-reactive
     
    2.1.3.RELEASE   

2.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 resolve(ServerWebExchange exchange) {
            	/**
            	* 限流条件:
            	* 1.用户ip地址(桶是私有)
				* 2.用户用户名(桶是私有)
				* 3.微服的路径(桶是共享的)
				*/
				//此处根据用户的id做为条件限流
                return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
            }
        };
    }

}

3.application.yml文件中配置

其实关键就是在filters中加入name,args的配置,可以对每个服务单独配置;
gateway限流之令牌桶算法_第1张图片

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  redis:
    host: xxx.xx.xx.xx(填写你自己的redis所在主机的ip)
    port: 6379
    password: (如果你的redis配置了密码请加上,没有可省略)
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter #请求数限流 名字不能随便写
              args:
                key-resolver: "#{@ipKeyResolver}"
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
                redis-rate-limiter.burstCapacity: 5 #令牌桶总容量
#            - After=2020-09-24T22:18:11.242+08:00[GMT+08:00]
#            - Cookie=username,zzyy
#            - Header=X-Request-Id, \d+   #请求头中要有X-Request-Id属性并且值为整数的正则表达式
#          filters:
#            - AddRequestHeader=X-Request-red, blue

        - id: payment_routh2
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
          filters:
#            - StripPrefix=1
            - name: RequestRateLimiter #请求数限流 名字不能随便写
              args:
                key-resolver: "#{@ipKeyResolver}"
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
                redis-rate-limiter.burstCapacity: 5 #令牌桶总容量

        - id: payment_routh3
          uri: http://news.baidu.com
          predicates:
            - Path=/guonei   #断言,路径相匹配的进行路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

到这里我们就配置好了,只需要启动项目就有限流效果了,测试的时候都设置为1,然后页面我们可以访问来看到限流效果;
但在这里用专业的工具Jmeter来测试会更加能显示限流的功能之强大和控制之精准!
4. 效果测试:

这里我直接贴效果图,如果想知道具体操作,可点击我的另一篇文章具体介绍Jmeter的操作,点击传送门;

测试1:
jmeter参数如下图:
gateway限流之令牌桶算法_第2张图片意思是1秒钟启动10个线程去发起请求,只执行一次;

            redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
            redis-rate-limiter.burstCapacity: 5 #令牌桶总容量

桶容量为5个,1秒钟加入一个,那么理论上用已经设置好的jemter请求参数,那就是10个请求应该有6个成功才对;
gateway限流之令牌桶算法_第3张图片gateway限流之令牌桶算法_第4张图片测试2:
jmeter参数如下图:
gateway限流之令牌桶算法_第5张图片

意思是3秒钟启动15个线程去发起请求,只执行一次;

           redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
           redis-rate-limiter.burstCapacity: 5 #令牌桶总容量

桶容量为5个,1秒钟加入1个,三秒钟就是3个,那么理论上,那就是15个请求应该有5+1*3=8个成功才对;
gateway限流之令牌桶算法_第6张图片gateway限流之令牌桶算法_第7张图片

参考大神博客:原文链接

你可能感兴趣的:(java,jmeter,网关)