问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Spring Cloud Gateway限流和流量控制

创作时间:
作者:
@小白创作中心

Spring Cloud Gateway限流和流量控制

引用
CSDN
1.
https://blog.csdn.net/u010020088/article/details/143790858

限流和流量控制是API网关的重要功能,能够防止后端服务过载,确保系统在高并发和流量突增的情况下依然能够稳定运行。Spring Cloud Gateway提供了多种限流和流量控制策略,常见限流算法如下。

常见限流算法

1.漏桶算法(不推荐)

  1. 原理:将请求缓存到一个队列中,然后以固定的速度处理,从而达到限流的目的
  2. 实现:将请求装到一个桶中,桶的容量为固定的一个值,当桶装满之后,就会将请求丢弃掉,桶底部有一个洞,以固定的速率流出。
  3. 举例:桶的容量为1W,有10W并发请求,最多只能将1W请求放入桶中,其余请求全部丢弃,以固定的速度处理请求
  4. 缺点:处理突发流量效率低(处理请求的速度不变,效率很低)

2.令牌桶算法(推荐)

  1. 原理:将请求放在一个缓冲队列中,拿到令牌后才能进行处理
  2. 实现:装令牌的桶大小固定,当令牌装满后,则不能将令牌放入其中;每次请求都会到桶中拿取一个令牌才能放行,没有令牌时即丢弃请求/继续放入缓存队列中等待
  3. 举例:桶的容量为10w个,生产1w个/s,有10W的并发请求,以每秒10W个/s速度处理,随着桶中的令牌很快用完,速度又慢慢降下来啦,而生产令牌的速度趋于一致1w个/s
  4. 缺点:处理突发流量提供了系统性能,但是对系统造成了一定的压力,桶的大小不合理,甚至会压垮系统(处理1亿的并发请求,将桶的大小设置为1,这个系统一下就凉凉啦)

使用Spring Cloud Gateway进行限流

Spring Cloud Gateway内置了基于Redis的分布式限流器,你可以通过配置Redis限流过滤器来实现请求限流。

  1. 添加依赖

pom.xml文件中添加以下依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  1. 配置Redis限流器

application.yml中配置Redis限流器:

spring:
  redis:
    host: localhost
    port: 6379
  cloud:
    gateway:
      routes:
- id: user-service
          uri: lb://USER-SERVICE
          predicates:
- Path=/users/**
          filters:
- name: RequestRateLimiter
              args:
                redis-rate-limiter:
                  replenishRate: 10
                  burstCapacity: 20
server:
  port: 8080
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    fetch-registry: true
    register-with-eureka: true
  1. 配置限流键解析器

创建一个自定义限流键解析器HostAddrKeyResolver.java

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class RateLimiterConfig {
  @Bean
  public KeyResolver hostAddrKeyResolver() {
      return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
  }
}
  1. 配置限流策略

application.yml中配置限流策略:

spring:
  cloud:
    gateway:
      default-filters:
- name: RequestRateLimiter
          args:
            key-resolver: "#{@hostAddrKeyResolver}"
            redis-rate-limiter:
              replenishRate: 10
              burstCapacity: 20

使用Resilience4j实现限流和熔断

Resilience4j是一个轻量级的故障处理库,支持限流、熔断、重试等功能。你可以通过集成Resilience4j来增强Spring Cloud Gateway的稳定性和容错能力。

  1. 添加依赖

pom.xml文件中添加以下依赖:

<dependency>
  <groupId>io.github.resilience4j</groupId>
  <artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
  1. 配置Resilience4j

application.yml中配置Resilience4j:

spring:
  cloud:
    gateway:
      routes:
- id: product-service
          uri: lb://PRODUCT-SERVICE
          predicates:
- Path=/products/**
          filters:
- name: CircuitBreaker
              args:
                name: myCircuitBreaker
                fallbackUri: forward:/fallback
resilience4j:
  circuitbreaker:
    instances:
      myCircuitBreaker:
        registerHealthIndicator: true
        ringBufferSizeInClosedState: 5
        ringBufferSizeInHalfOpenState: 2
        waitDurationInOpenState: 10000
        failureRateThreshold: 50
        eventConsumerBufferSize: 10
  1. 创建熔断器的回退处理

创建一个回退处理控制器FallbackController.java

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FallbackController {
  @GetMapping("/fallback")
  public String fallback() {
      return "This is a fallback response";
  }
}

一个完整的示例

为了更好地理解上述概念,我们来看一个完整的限流和流量控制配置示例。假设我们有一个电商平台,有用户服务、订单服务和产品服务。我们需要配置Gateway来实现限流、流量控制和熔断功能。

完整的Spring Cloud Gateway配置:

spring:
  application:
    name: gateway-service
  redis:
    host: localhost
    port: 6379
  cloud:
    gateway:
      routes:
- id: user-service
          uri: lb://USER-SERVICE
          predicates:
- Path=/users/**
          filters:
- name: RequestRateLimiter
              args:
                redis-rate-limiter:
                  replenishRate: 10
                  burstCapacity: 20
- id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
- Path=/orders/**
- id: product-service
          uri: lb://PRODUCT-SERVICE
          predicates:
- Path=/products/**
          filters:
- name: CircuitBreaker
              args:
                name: myCircuitBreaker
                fallbackUri: forward:/fallback
      default-filters:
- name: RequestRateLimiter
          args:
            key-resolver: "#{@hostAddrKeyResolver}"
            redis-rate-limiter:
              replenishRate: 10
              burstCapacity: 20
server:
  port: 8080
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    fetch-registry: true
    register-with-eureka: true
resilience4j:
  circuitbreaker:
    instances:
      myCircuitBreaker:
        registerHealthIndicator: true
        ringBufferSizeInClosedState: 5
        ringBufferSizeInHalfOpenState: 2
        waitDurationInOpenState: 10000
        failureRateThreshold: 50
        eventConsumerBufferSize: 10
management:
  endpoints:
    web:
      exposure:
        include: "*"

启动和测试:

  1. 启动Redis服务:
docker run -d -p 6379:6379 redis
  1. 启动Eureka服务注册中心:
# 启动Eureka服务注册中心
java -jar eureka-server.jar
  1. 启动用户服务、订单服务和产品服务:
# 启动用户服务
java -jar user-service.jar
# 启动订单服务
java -jar order-service.jar
# 启动产品服务
java -jar product-service.jar
  1. 启动Gateway服务:
java -jar gateway-service.jar
  1. 测试限流和流量控制配置:
访问 http://localhost:8080/users 应该受到限流控制,每秒最多10次请求,突发请求不超过20次。
访问 http://localhost:8080/products 时,如果服务故障,会触发Resilience4j熔断器并返回回退响应。

结论

通过本文的讲解,你应该已经掌握了如何在Spring Cloud Gateway中实现限流和流量控制。我们详细介绍了如何使用Redis限流器、配置限流键解析器、自定义限流策略,以及使用Resilience4j实现限流和熔断,帮助你构建一个稳定、高可用的API网关。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号