NGINX的漏桶算法限流与gateway的令牌桶算法限流

简单来讲漏桶算法与令牌桶算法的区别

漏桶算法是指请求会打入到一个“桶”中,桶会以一定速率将请求递交下去。当请求过多的时候,桶内会积累请求等待递交;当请求积累超过桶的大小时,请求就会向水满的桶一样溢出(被桶抛弃)

令牌桶算法是指桶会以固定的速率生成令牌并存入桶中,桶满后会暂停生成,当请求打过来的时候会去桶中申请令牌,只有携带令牌的请求才能顺利递交。不携带令牌的请求会被阻塞/抛弃

漏桶算法处理请求会更加平滑稳定,而令牌桶算法处理请求波动会比较高;

在面对突发情况时,令牌桶算法可以更好的接住并处理请求(秒杀等短时间高并发现象)

NGINX的漏桶限流具有两种方法:

1.控制速率

语法limit_req_zone key zone rate

  • key定义了限流对象。
    • $binary_remote_addr就是其中一种key,基于客户端IP限流。
    • $server_name基于请求的服务器限流,不太常用;
    • $url/#requeset_url基于请求URL限流,当URL包含查询参数时可能会导致大量的key,也不常用
  • Zone:定义了共享存储区来存储访问信息,下述例子中定义了存储区域名为one,并为其分配了10M的存储空间.即zone=存储空间名:存储大小
  • rate:定义了最大访问速率,例如rate=10m/s表示每秒最多请求10个请求
  • burst,指定桶的大小,超过桶的存储就会被丢弃
  • nodelay:快速处理

语法 limit_req_status 指定当请求被返回时会返回HTTP状态码为429

 举例:

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=12r/m;
    limit_req_status 429;
    server {
        location / { #这里是指为所有请求都添加了下述内容
            limit_req zone=one burst=20 nodelay; #这里是为了启用上述限流区域名为one的漏桶
        }
}

2.控制并发数

这里主要是limit_req_zone改成limit_conn_zone

$binary_remote_addr:表示一个ip最多只能持有多少链接

$server_name:表示一个服务器最多支持同时处理多少并发链接

举例

http{
      limit_conn_zone $binary_remote_addr zone=perip:20m;
      limit_conn_zone $server_name zone=perserver:10m;        
      server{
           location / {
                  limit_conn perip 20; 
                  limit_conn perserver 100; 
          }  
    }  
}    

spring cloud gateway的令牌桶限流算法:

首先令牌桶算法默认基于redis,也就是说需要在gateway配置上redis后才可以使用

在微服务路由的yaml配置中添加局部过滤器RequestRateLimiter

server:
  port: 63010 # 网关端口
spring:
  cloud:
    gateway:
      routes: # 网关路由配置
        - id: content-api # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://content-api # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/content/** # 这个是按照路径匹配,只要以/content/开头就符合要求
     filters:
            - name:RequestRateLimiter
              args:
                 key-resolver: '#{@pathKeyResolver}' # 使用spEL从容器中取对象
                 redis-rate-limiter.replenishRate: 1 # 令牌桶每秒填充平均速率
                 redis-rate-limiter.burstCapacity: 3 # 令牌桶的上限
  redis:
    host: x.x.x.x
    port: 6379

关于@pathKeyResolver,下述例子使用HTTP请求作为key,在redis中存储并检索速率限制信息

@Configuration  
public class GatewayConfig {  
  
    @Bean  
    public KeyResolver myKeyResolver() {  
        return exchange -> Mono.just(exchange.getRequest().getPath().value());  
    }  
}

 

posted @ 2024-09-12 17:41  天启A  阅读(221)  评论(0)    收藏  举报