关于云计算:Spring-Cloud-Gateway限流实战

欢送拜访我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,波及Java、Docker、Kubernetes、DevOPS等;

本篇概览

  • 本文是《Spring Cloud Gateway实战》系列的第八篇,通过后面的学习,咱们对过滤器已理解得差不多,明天来补全过滤器的最初一个版块:限流(RequestRateLimiter )
  • 默认的限流器是基于redis实现的,限流算法是大家相熟的令牌桶(Token Bucket Algorithm),对于令牌捅的原理就不在此开展了,聪慧的您看一眼下图应该就懂了:装令牌的桶容量无限,例如最多20个,令牌进入桶的速度恒定(留神,这里是和漏桶算法的区别),例如每秒10个,底部每个申请能拿到令牌才会被解决:

RequestRateLimiter根本套路

  • 应用RequestRateLimiter过滤器的步骤非常简单:
  1. 筹备可用的redis
  2. maven或者gradle中增加依赖<font color=”blue”>org.springframework.boot:spring-boot-starter-data-redis-reactive</font>
  3. 确定依照什么维度限流,例如依照申请中的username参数限流,这是通过编写KeyResolver接口的实现来实现的
  4. 配置application.yml文件,增加过滤器
  • 以上就是应用RequestRateLimiter过滤器的套路了,简略么?接下来,咱们先编码再验证

源码下载

  • 本篇实战中的残缺源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blo…):
名称 链接 备注
我的项目主页 https://github.com/zq2599/blo… 该我的项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blo… 该我的项目源码的仓库地址,https协定
git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该我的项目源码的仓库地址,ssh协定
  • 这个git我的项目中有多个文件夹,本篇的源码在<font color=”blue”>spring-cloud-tutorials</font>文件夹下,如下图红框所示:

  • <font color=”blue”>spring-cloud-tutorials</font>文件夹下有多个子工程,本篇的代码是<font color=”red”>gateway-requestratelimiter</font>,如下图红框所示:

筹备工作

  • 为了更好的演示Gateway的成果,在服务提供者<font color=”blue”>provider-hello</font>的代码(Hello.java)中新增一个web接口,能够承受一个入参:
    @GetMapping("/userinfo")
    public String userInfo(@RequestParam("username") String username) {
        return Constants.HELLO_PREFIX + " " + username + ", " + dateStr();
    }
  • 前面的测试咱们就用上述接口;

编码

  • 在父工程<font color=”blue”>spring-cloud-tutorials</font>之下新增子工程<font color=”red”>gateway-requestratelimiter</font>,其pom.xml内容如下,重点是<font color=”blue”>org.springframework.boot:spring-boot-starter-data-redis-reactive</font>:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-tutorials</artifactId>
        <groupId>com.bolingcavalry</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway-requestratelimiter</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.bolingcavalry</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
    </dependencies>
</project>
  • 配置文件application.yml,请留神RequestRateLimiter的几个参数,曾经用中文增加了具体的正文:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: circuitbreaker-gateway
  # redis配置
  redis:
    host: 192.168.50.43
    port: 6379

  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - name: RequestRateLimiter
              args:
                  # 令牌入桶的速度为每秒100个,相当于QPS
                redis-rate-limiter.replenishRate: 100
                # 桶内能装200个令牌,相当于峰值,要留神的是:第一秒从桶内能去200个,然而第二秒只能取到100个了,因为入桶速度是每秒100个
                redis-rate-limiter.burstCapacity: 200
                # 每个申请须要的令牌数
                redis-rate-limiter.requestedTokens: 1
  • 指定限流维度的代码CustomizeConfig.java,这里是依据申请参数<font color=”blue”>username</font>的值来限流的,假如实在申请中一半申请的username的等于<font color=”red”>Tom</font>,另一半的username的等于<font color=”red”>Jerry</font>,依照application.yml的配置,Tom的申请QPS为10,Jerry的QPS也是10:
package com.bolingcavalry.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import java.util.Objects;

@Configuration
public class CustomizeConfig {
    @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username"));
    }
}
  • 毫无养分的启动类RequestRateLimiterApplication.java:
package com.bolingcavalry.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RequestRateLimiterApplication {
    public static void main(String[] args) {
        SpringApplication.run(RequestRateLimiterApplication.class,args);
    }
}
  • 代码写完了,接下来开始验证;

验证(桶容量等于入桶速度)

  • 首先验证的是桶容量等于入桶速度时的成果,请批改<font color=”blue”>gateway-requestratelimiter</font>利用的application.yml中文件,使得redis-rate-limiter.replenishRate和redis-rate-limiter.burstCapacity的值都等于100,也就是说桶的大小等于100,每秒放入的令牌数也是100
  • 确保redis曾经启动,并且与application.yml中的配置放弃始终
  • 启动nacos(provider-hello依赖)
  • 启动服务提供者<font color=”blue”>provider-hello</font>
  • 启动<font color=”blue”>gateway-requestratelimiter</font>
  • 为了模仿web申请,我这里应用了<font color=”blue”>Apache Benchmark</font>,windows版本的下载地址:
    https://www.apachelounge.com/…
  • 上述文件下载解压后即可应用,在控制台进入<font color=”blue”>Apache24\bin</font>后执行以下命令,意思是向指定地址发送10000个申请,并发数为2:
ab -n 10000  -c 2 http://localhost:8081/hello/userinfo?username=Tom
  • 控制台输入如下,可见不到八秒的工夫,只胜利了800个,证实限流合乎预期:

验证(桶容量大于入桶速度)

  • 接下来试试桶容量大于入桶速度时的限流成果,这对于咱们管制峰值响应有很重要的参考价值
  • 请批改<font color=”blue”>gateway-requestratelimiter</font>利用的application.yml中文件,redis-rate-limiter.replenishRate维持<font color=”blue”>100</font>不变,然而redis-rate-limiter.burstCapacity改成<font color=”red”>200</font>,也就是说每秒放入的令牌数还是100,但桶的容量翻倍了
  • 重启利用<font color=”blue”>gateway-requestratelimiter</font>
  • 再次执行以下命令,意思是向指定地址发送10000个申请,并发数为2:
ab -n 10000  -c 2 http://localhost:8081/hello/userinfo?username=Tom
  • 测试后果如下图,可见合乎预期,能够将桶内令牌全副用掉,以撑持峰值超过QPS的场景:

验证(依据username的维度限流)

  • 接下来验证限流的维度,到底是不是依照申请参数username的值来限流的
  • 咱们关上两个命令行,同时发送申请(动作要快),第一个的username等于<font color=”blue”>Tom</font>,第二个等于<font color=”blue”>Jerry</font>,实践上揣测,如果都是8秒内实现,那么每个命令都有900个申请能胜利
  • 测试后果如下图,可见合乎预期,每个username用的是本人的令牌:

  • 至此,Spring Cloud Gateway限流实战曾经实现,如此简略易用的限流计划,心愿能给您的学习和应用带来参考

你不孤独,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢送关注公众号:程序员欣宸

微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游Java世界…
https://github.com/zq2599/blog_demos

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理