1. 配置 Nginx 限流包含哪些部分?

核心比喻:像“幼儿园门卫”一样控制入园人数
  • 问题:
    如果很多小朋友突然挤进幼儿园(大量请求),门卫无法管理,教室会被挤垮!
  • 核心组成部分:
    1. 全局限流配置:定义限流规则(如每秒最多10次请求)。
    2. 速率限制模块:limit_req 控制请求速率。
    3. 连接数限制模块:limit_conn 控制同时连接数。
    4. 共享内存区域:存储IP的请求计数。
    5. 错误处理:超过限制时返回503错误。

2. 使用场景

  • 高流量网站:
    如电商大促时,防止服务器被压垮。
  • API接口:
    限制第三方调用频率(如每秒最多10次)。
  • 防止恶意爬虫:
    拦截频繁访问的爬虫(如每秒超过50次请求)。
  • 资源保护:
    限制核心接口的并发连接数(如支付接口)。

3. 底层原理

(1) 如何限流?
  1. limit_req 模块:
    • 令牌桶算法:
      每秒生成固定数量的“令牌”,请求需要先获取令牌才能进入。
      • rate=10r/s:每秒生成10个令牌。
      • burst=20:允许突发20次请求(但平均速率不能超过10r/s)。
  2. limit_conn 模块:
    • 控制单个IP的并发连接数(如同时最多允许5个连接)。
  3. 共享内存区域:
    • Nginx用内存记录每个IP的请求次数和连接数,速度快且高效。
(2) 核心机制
  • 全局配置:
    在 http 块中定义共享内存区域(如 limit_req_zone)。
  • 局部应用:
    在 server 或 location 块中引用配置(如 limit_req zone=one)。
  • 动态调整:
    通过参数 burst 和 nodelay 控制突发流量和延迟策略。

4. 流程图

以下是 Nginx 限流的流程:

+-------------------+
| 用户发送请求      |  (如访问商品页面)
+-------------------+
         |
         v
+-------------------+
| Nginx检查限流规则  |  (如每秒最多10次请求)
+-------------------+
         |
         v
+-------------------+
| 判断是否超限       |  (是 → 返回503;否 → 继续处理)
+-------------------+
         |
         v
+-------------------+
| 返回结果给用户    |  (合法请求正常处理)
+-------------------+

5. 概念图

以下是 Nginx 限流的核心概念:

+-------------------+
| Nginx限流配置      |
+-------------------+
         |
         v
+-------------------+
| 共享内存区域       |  (存储IP的计数)
+-------------------+
         |
         v
+-------------------+
| 速率限制模块       |  (limit_req 控制请求速率)
+-------------------+
         |
         v
+-------------------+
| 连接数限制模块     |  (limit_conn 控制并发连接)
+-------------------+
         |
         v
+-------------------+
| 错误响应          |  (返回503 Too Many Requests)
+-------------------+

6. UML 类图

以下是简化后的 UML 类图(用配置块表示):

+-------------------+
| Nginx配置         |
+-------------------+
| - http块          |  (全局配置区域)
| - server块        |  (虚拟主机配置)
| - location块      |  (路径级配置)
+-------------------+

+-------------------+
| limit_req_zone     |
+-------------------+
| - key: string      |  (如 $binary_remote_addr)
| - rate: string     |  (如 10r/s)
| - zone: string     |  (共享内存区域名称和大小)
+-------------------+

+-------------------+
| limit_req          |
+-------------------+
| - zone: string     |  (引用共享内存区域)
| - burst: int       |  (突发请求数)
| - nodelay: bool    |  (是否允许直接使用突发令牌)
+-------------------+

7. 思维导图

以下是 Nginx 限流的思维导图:

+-------------------+
| Nginx限流配置      |
+-------------------+
| + 核心模块        |
|   + limit_req      |
|   + limit_conn     |
| + 共享内存区域    |
|   + key            |
|   + rate           |
|   + zone           |
| + 参数说明        |
|   + burst          |
|   + nodelay        |
| + 使用场景        |
|   + 防止DDoS       |
|   + API限流        |
+-------------------+

8. 实例代码(Nginx 配置示例)

以下是完整的 Nginx 配置文件示例:

# 1. 全局配置:定义共享内存区域
http {
    # 定义速率限制区域(limit_req_zone)
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; # (a) 每秒最多10次请求
    limit_req_zone $server_name zone=per_server:10m rate=100r/s; # (b) 每个虚拟主机每秒最多100次请求

    # 定义连接数限制区域(limit_conn_zone)
    limit_conn_zone $binary_remote_addr zone=addr_conn:10m; # (c) 按IP限制连接数
    limit_conn_zone $server_name zone=per_server_conn:10m; # (d) 按服务器名称限制连接数
}

server {
    listen 80;
    server_name example.com;

    # 2. 应用限流到特定路径(如API接口)
    location /api/ {
        # 应用速率限制
        limit_req zone=one burst=20 nodelay=on; # (e) 允许突发20次请求,且立即使用令牌

        # 应用连接数限制
        limit_conn addr_conn 5; # (f) 同一IP最多5个并发连接

        # 其他配置(如代理到PHP)
        proxy_pass http://backend;
    }

    # 3. 全局限流(所有请求)
    limit_req zone=per_server burst=100 nodelay=off; # (g) 每个服务器每秒最多100次请求,突发100次需排队
    limit_conn per_server_conn 100; # (h) 每个服务器最多100个并发连接

    # 4. 错误页面配置
    error_page 503 /503.html; # (i) 超限时显示自定义页面
    location = /503.html {
        internal;
        root /var/www/html;
    }
}

代码注释详细解释

第 1 步:定义共享内存区域
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
  1. 作用:定义一个名为 one 的共享内存区域,存储IP的请求计数。
  2. 为什么这么写:
    • $binary_remote_addr 是IP的二进制形式,节省内存。
    • 10m 是内存大小(10MB,可存储约6万个IP计数)。
  3. 知识点:Nginx 的 limit_req_zone 配置语法。
第 2 步:引用限流规则
limit_req zone=one burst=20 nodelay=on;
  1. 作用:在 /api/ 路径应用 one 区域的限流规则。
  2. 为什么这么写:
    • burst=20:允许突发20次请求。
    • nodelay=on:突发请求立即处理,无需排队。
  3. 知识点:limit_req 模块参数。
第 3 步:连接数限制
limit_conn addr_conn 5;
  1. 作用:限制同一IP的并发连接数为5。
  2. 为什么这么写:防止单IP占用过多服务器资源。
  3. 知识点:limit_conn 模块的使用。
第 4 步:错误页面配置
error_page 503 /503.html;
  1. 作用:当请求被限流时,显示自定义的503页面。
  2. 为什么这么写:提升用户体验,避免直接看到Nginx默认错误页。
  3. 知识点:Nginx 的错误页面重定向。

9. 详细说明

(1) 速率限制参数
  • rate=10r/s:
    每秒生成10个令牌,每个请求消耗1个令牌。
  • burst=20:
    允许在短时间内超过速率,但总请求不能超过速率+突发值。
    • 示例:1秒内允许30次请求(10r/s × 1秒 + 20突发)。
  • nodelay:
    • on:突发请求直接使用令牌,无需排队。
    • off:突发请求需排队等待。
(2) 共享内存区域
  • zone=one:10m:
    • one:区域名称。
    • 10m:内存大小,存储更多IP的计数。
(3) 连接数限制
  • limit_conn addr_conn 5:
    同一IP同时最多5个连接,超过则拒绝。

10. 总结

  • Nginx限流是“幼儿园门卫系统”:
    • limit_req:控制小朋友进入速度(每秒最多10个)。
    • limit_conn:控制滑梯区同时只能有5个小朋友。
  • 核心步骤:
    1. 在 http 块定义共享内存区域。
    2. 在 server 或 location 块应用限流规则。
  • 底层原理:
    通过令牌桶算法和共享内存计数,动态控制请求速率和并发连接数。

11. 扩展问题解答

Q1: 为什么用 binary_remote_addr 而不是 remote_addr?
  • A1:二进制IP地址更节省内存(存储空间减少)。
Q2: 如何测试限流是否生效?
  • A2:
    • 使用 ab 工具模拟高并发请求:
      ab -n 100 -c 10 http://example.com/api/
      
    • 观察是否返回503错误。
Q3: 如何限制特定路径?
  • A3:在 location 块中单独配置限流规则(如示例中的 /api/)。

12. 完整配置示例(含注释)

# 1. 定义全局限流区域
http {
    # 速率限制:按IP限制,每秒最多10次,存储在10MB内存中
    limit_req_zone $binary_remote_addr zone=ip_rate_limit:10m rate=10r/s; # (a) 定义IP限流区域

    # 连接数限制:按IP限制,最多5个并发连接
    limit_conn_zone $binary_remote_addr zone=ip_conn_limit:10m; # (b) 定义连接数区域

    server {
        listen 80;
        server_name myapp.com;

        # 2. 应用限流到特定路径(如API)
        location /api/ {
            # 应用IP速率限制
            limit_req zone=ip_rate_limit burst=20 nodelay=on; # (c) 允许突发20次请求

            # 应用连接数限制
            limit_conn ip_conn_limit 5; # (d) 同一IP最多5个并发连接

            # 其他配置(如反向代理)
            proxy_pass http://backend;
        }

        # 3. 全局限流(所有请求)
        limit_req zone=ip_rate_limit burst=30 nodelay=off; # (e) 全局速率限制,突发需排队

        # 4. 连接数全局限制(整个服务器)
        limit_conn ip_conn_limit 100; # (f) 服务器最多100个并发连接

        # 5. 错误页面配置
        error_page 503 /custom_503.html;
        location = /custom_503.html {
            root /var/www/html;
            internal;
        }
    }
}

13. 总结

  • Nginx限流是“幼儿园的门卫规则”:
    • 通过 limit_req 控制进入速度。
    • 通过 limit_conn 控制同时人数。
  • 核心作用:
    防止服务器被恶意请求压垮,保护资源。
  • 底层原理:
    使用共享内存存储计数,结合令牌桶算法动态控制流量。

14. 关键知识点总结

指令作用示例
limit_req_zone定义速率限制区域控制IP每秒请求次数
limit_req应用速率限制到路径或服务器在 /api/ 限流
limit_conn_zone定义连接数限制区域按IP限制并发连接数
limit_conn应用连接数限制到路径或服务器同一IP最多5个连接
burst允许的突发请求量burst=20 允许突发20次
nodelay是否立即处理突发请求on → 直接处理

15. 总结

  • 配置 Nginx 限流是“设置幼儿园规则”:
    • 通过 limit_req 控制请求速度,limit_conn 控制同时人数。
  • 核心步骤:
    1. 定义共享内存区域。
    2. 在路径或服务器上应用限流规则。
    3. 配置错误页面提升体验。
  • 底层原理:
    令牌桶算法和共享内存计数,动态控制流量。

更多推荐