微服务-服务限流

198 阅读2分钟

一、为什么要限流?

  1. 并发量特别大(突然流量)。
  2. 防止用户恶意刷接口。

二、限流的实现方式

限流的实现方式有以下几种:

  • tomcat: 可以设置最大连接数
  • Nginx: 漏桶算法
  • 网关:令牌
  • 桶算法
  • 自定义拦截器

2.1 tomcat限流

可以在tomcat中设置最大线程数maxThreads。每一次HTTP请求到达WEB服务,Tomcat都会创建一个线程来处理该请求,那么最大线程数决定了web服务容器可以同时处理多少个请求。

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="2000" maxThreads="50" redirectPort="8443">

不过使用tomcat做限流适合用在单体项目中,不适合分布式服务。

2.1 Nginx限流

2.1.1 漏桶算法,控制速率

1691498857912.jpg

漏桶的大小是固定的;漏出请求的速率也是固定的;如果漏桶已经满了,那么多么请求需要等待或直接丢弃。

http{
    limit_req_zone $binary_remote_addr zone=service1RateLimit:10m rate=10r/s
    server{
        listen  80;
        server_name localhost;
        location / {
            limit_req_zone = service1RateLimit burst=20 nodelay;
            proxy_pass http://targetserver;
        }
    }
}
  • 语法:limit_req_zone key zone rate
  • key:定义限流对象,binary_remote_addr就是一种key,基于客户端IP限流
  • zone:定义共享存储区来存储访问信息,10m指申请了10m的内存空间,可以存储16w个 IP地址访问信息
  • rate:最大访问速率,rate=10r/s,表示每秒最多处理10个请求
  • burst:相当于桶的大小
  • nodelay: 快速处理。桶中请求要快速处理,桶满后的多余请求要快速抛弃。
  • service1RateLimit:自定义标识
2.1.2 控制并发连接数
http{
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    server{
        listen  80;
        server_name localhost;
        location / {
            ...
            limit_conn perip 20;
            limit_conn perserver 100;
            proxy_pass http://targetservser;
        }
    }
}
  • limit_conn perip 20: 对应的key是$binary_remote_addr,表示限制单个IP同时最多能支持20个连接。
  • limit_conn perserver 100:对应的key是$server_name,表示虚拟主机(server)同时能处理并发连接的总数。

2.2 gateway网关限流

1691502694046.jpg

yml配置文件中,微服务路由设置添加局部过滤器RequestRateLimiter

- id: gateway-consumer
  url: lb://GATEWAY-CONSUMER
  predicates:
  - Path=/order/**
  filters:
    - name: RequestRateLimiter
      args: 
        # 使用SpEL从容器中获取对象
        key-resolver: '#{@pathKeyResolver}'
        # 令牌桶每秒填充平均速率
        redis-rate-limiter.replenishRate: 1
        # 令牌桶的上限
        redis-rate-limiter.burstCapacity: 3
  • key-resolver: 定义限流对象(ip、路径、参数),需代码实现,使用spel表达式获取
  • replenishRate: 令牌桶每秒填充平均速率。
  • burstCapacity: 令牌桶总容量。
  • 令牌默认是存储到redis的,在网关的配置文件中需要配置redis连接。

令牌桶算法与漏桶算法的区别

  1. 令牌桶存储的是令牌,漏桶存储的是请求。
  2. 处理请求的速率不同。
    • 令牌桶处理请求的速率是不固定的。如果桶中已经有令牌,可以同时处理令牌数量个请求;如果桶中没有令牌,需要等待令牌生成后再处理请求。
    • 漏桶以固定速率漏出请求,以恒定速度放行请求

令牌桶算法与漏桶算法的共同点

  1. 都可以处理突发请求。