• 实战讲解SpringCloud网关接口限流SpringCloudGateway+Redis(图+文)


    1 缘起

    最近补充微服务网关相关知识,学习了网关相关概念,
    了解网关在微服务中存在的意义及其使命,如统一用户认证、接口权限控制、接口限流、接口熔断、黑白名单机制等,
    打算通过实践的方式逐步学习网关的相关功能,同时分享网关应用系列文章。
    本文分享通过网关实现接口限流,构建相关服务,帮助读者轻松应对知识考核与交流。

    2 架构

    本文的服务架构如下图所示,
    由图可知,应用架构共有三个部分:网关、注册中心和服务,
    通过网关进行接口限流,当然是在网关中做文章,实现接口的流量控制。
    本套架构基于Spring原生的组件,其中,网关:SpringCloudGateway,注册中心:Eureka,服务:SpringBoot。
    在这里插入图片描述

    3 Gateway配置

    使用Gateway进行接口限流,注解当然是Gateway服务,
    如下配置均是对Gateway服务进行的,其他的服务各自按照需要准备好即可,
    需要注意的是:其他服务与网关应该在同一个注册中心。

    3.1 依赖

    学技术,讲版本。
    SpringBoot与SpringCloud的版本对应关系如下表:
    官网查询地址:https://start.spring.io/actuator/info

    序号SpringCloud版本SpringBoot版本
    1Edgware1.5.x
    2Finchley2.0.x
    3Greenwich2.1.x
    4Hoxton.SR12[2.2.0.RELEASE, 2.4.0.M1)
    52020.0.6[2.4.0.M1, 2.6.0-M1)
    62021.0.0-M1[2.6.0-M1, 2.6.0-M3)
    72021.0.0-M3[2.6.0-M3, 2.6.0-RC1)
    82021.0.0-RC1[2.6.0-RC1, 2.6.1)
    92021.0.5[2.6.1, 3.0.0-M1)
    102022.0.0-M1[3.0.0-M1, 3.0.0-M2)
    112022.0.0-M2[3.0.0-M2, 3.0.0-M3)
    122022.0.0-M3[3.0.0-M3, 3.0.0-M4)
    132022.0.0-M4[3.0.0-M4, 3.0.0-M5)
    142022.0.0-M5[3.0.0-M5, 3.0.0-RC1)
    152022.0.0-RC1[3.0.0-RC1, 3.1.0-M1)

    3.1.1 SpringBoot

    SpringBoot版本:2.2.8.RELEASE。

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.8.RELEASEversion>
        <relativePath/> 
    parent>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.1.2 SpringCloud

    SpringCloud提供微服务相关组件。

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>Hoxton.SR5version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.1.3 注册中心&网关&Redis

    注册中心:网关为了发现注册中心的服务,配置uri进行限流;
    网关:网关配置的基础组件;
    Redis:存储限流使用的令牌(Token)。

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        <version>2.2.3.RELEASEversion>
    dependency>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.2 创建拦截类型Bean

    为什么创建拦截类型Bean?
    SpringCloud Gateway中可以自定义配置拦截方式,
    通过Spring正则表达式(SpEL)匹配对应的拦截Bean,
    所以,要创建接口拦截方式的Bean。
    其中,拦截有三种方式:路径拦截、IP拦截和参数拦截,
    配置样例如下:

    package com.monkey.gateway_template.config;
    
    import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import reactor.core.publisher.Mono;
    
    /**
     * 请求限流配置.
     *
     * @author xindaqi
     * @since 2022-11-16 18:19
     */
    @Configuration
    public class RequestRateLimiter {
    
        @Primary
        @Bean
        KeyResolver ipKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
        }
    
        @Bean
        KeyResolver apiKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getPath().value());
        }
        @Bean
        KeyResolver paramKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("param-name"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    3.3 限流配置

    SpringCloud Gateway的限流算法采用令牌桶限流,
    结合Redis,将令牌存储与Redis,提高读写性能。
    网关限流配置的最核心部分如下,
    其中,
    (1)通过动态路由方式获取注册中心的服务:uri: lb://service-name;
    (2)断言路径predicates Path,为了使限流生效,路径不可与服务名称相同;
    (3)为使限流生效,需要去除配置的断言路径:StripPrefix=1;
    (4)过滤器名称为RequestRateLimiter,Redis约定的名称,不可更改。
    限流参数:
    (1)key-resolver: “#{@ipKeyResolver}”: 限流方式:Bean名称
    (2)redis-rate-limiter.replenishRate: 1生成令牌速率:个/秒
    (3)redis-rate-limiter.burstCapacity: 令牌桶容量,突发流量通过网关进入该接口时可处理的最大请求数
    (4)redis-rate-limiter.requestedTokens: 1 # 每次消费的Token数量

    server:
      port: 9001
    
    eureka:
      client:
        fetch-registry: true
        register-with-eureka: true
        service-url:
          defaultZone: http://localhost:8001/eureka/eureka
    
    spring:
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true # 开启以应用名代理服务,即通过应用名称访问接口
              lowerCaseServiceId: true # 微服务名称小写
          routes:
            - id: producer # 代理的服务ID,唯一
              uri: lb://producer # 代理的服务实例名称,开启微服务名称小写后,可使用小写的名称
              predicates:
                - Path=/producer-server/** # 断言路径,即通过该路径匹配代理的服务,为了使限流生效,路径不可与服务名称相同
              filters:
                - StripPrefix=1 # 去除producer-server,对后面的URI进行限流,保证限流生效
                - name: RequestRateLimiter # 使用Redis限流器
                  args:
                    key-resolver: "#{@ipKeyResolver}" # 限流方式:Bean名称
                    redis-rate-limiter.replenishRate: 1 # 生成令牌速率:个/秒
                    redis-rate-limiter.burstCapacity: 3 # 令牌桶容量
                    redis-rate-limiter.requestedTokens: 1 # 每次消费的Token数量
      redis:
        database: 0
        host: 127.0.0.1
        port: 6379
        password: 123456
        jedis:
          pool:
            max-active: 1 # 连接池:最大连接数,-1不限制
            max-idle: 8 # 连接池:最大空闲连接数量
            max-wait: 2000 # 连接池:最大阻塞等待时间,-1不限制,单位:毫秒
            min-idle: 0 # 连接池;最小空闲连接数量
          timeout: 1000 # 连接Redis服务器超时时间,单位:毫秒
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    4 测试

    4.1 Postman接口测试

    通过接入网关接入接口,Postman测试结果如下图所示。

    4.1.1 正常请求

    成功响应的结果如下图所示,由图可知,响应头中包含配置的限流参数。

    序号参数描述
    1X-RateLimit-Remaining剩余可请求次数
    2X-RateLimit-Requested-Tokens每次请求消耗的Token数量
    3X-RateLimit-Burst-Capacity令牌桶容量,接口可承载的最大峰值请求数量
    4X-RateLimit-Replenish-Rate令牌生成速率,个/秒

    在这里插入图片描述

    4.1.2 被丢弃的请求

    请求次数超过配置后,响应结果如下图所示,
    由图可知,响应的状态码为429,描述信息为:Too Many Requests。
    在这里插入图片描述
    SpringGateway生成的数据存储在Redis,样式如下图所示,
    由图可知,键名前缀为:request_rate_limiter.
    键名后缀为:tokens和timestamp。
    在这里插入图片描述

    4.2 JMeter测试

    为了更好地体验接口限流功能,使用JMeter配置多线程请求接口,
    测试结果如下图所示,由结果树可看到请求过程中,有正常的请求,有被拒绝的请求。

    4.2.1 正常请求

    正常的请求响应内容如下图所示。
    在这里插入图片描述

    4.2.2 被丢弃的请求

    被丢弃的请求响应内容如下图所示。
    在这里插入图片描述

    5 小结

    网关通过动态路由(lb:service-name)方式代理服务时,使限流生效需满足两个条件:
    (1)断言中配置的路径前缀不能与服务名称相同,如代理的服务为producer,断言(predicates)路径中的前缀禁止配置为producer;
    (2)过滤器(filters)必须配置StripPrefix=1,移除前缀,保证代理的接口可以进行限流;
    (3)过滤器名称为RequestRateLimiter,Redis约定的名称,不可更改。
    常用的限流方式有3钟,IP限流、路径限流和参数限流:
    (1)IP限流:exchange.getRequest().getRemoteAddress().getHostName()
    (2)路径限流:exchange.getRequest().getPath().value()
    (3)参数限流:exchange.getRequest().getQueryParams().getFirst(“param-name”)。

  • 相关阅读:
    LeetCode HOT 100 —— 75 .颜色分类
    Excel打开后关闭就马上跳出 Visual c++ Runtime Error R6025
    GB/T28181-2016 SDP定义和音视频传输模式解读
    【云原生系列】Docker学习
    [创业-38]:公司、企业、组织的本质与层次
    echarts地图区域高亮时,所在区域的symbol切换图片,类似跟着区域高亮
    esp32-rust-std-examples-blinky
    【leetcode41-----可被5整除的二进制前缀】
    加密和验签
    Web服务器实现|基于阻塞队列线程池的Http服务器|线程控制|Http协议
  • 原文地址:https://blog.csdn.net/Xin_101/article/details/127890605