Nginx限流应用


发布于 2025-01-21 / 9 阅读 / 0 评论 /
Nginx限流原理 限流配置 限流案例

Nginx原生提供限流功能,能有效保护服务器资源,防止恶意攻击和过度请求。

1.限流算法

主要有三种限流算法:固定窗口算法、漏桶算法和令牌桶算法。

1.1.固定窗口算法(ngx_http_limit_req_module)

允许你定义一个请求速率(例如每秒允许的请求数量)和一个时间窗口。当请求到达时,Nginx会检查在当前的时间窗口内是否已经达到了设置的速率限制。如果请求超出了速率限制,Nginx可以配置为返回错误状态码(如503 Service Temporarily Unavailable)或者延迟处理请求。

固定窗口算法主要通过limit_req_zone和limit_req指令来实现。limit_req_zone指令用于定义限流区域和相关参数,而limit_req指令则用于在特定的location或server块中启用限流。

1.2.漏桶算法(ngx_http_limit_conn_module)

漏桶算法是一种流量整形(Traffic Shaping)和流量控制(Rate Limiting)算法。它限制了同时处理的连接数,可以用来限制对某个资源(如服务器、数据库等)的并发访问数。当达到限制的连接数时,新的连接会被拒绝,直到现有的连接数降低。

漏桶算法主要通过limit_conn_zone和limit_conn指令来实现。limit_conn_zone指令用于定义连接限制区域和相关参数,而limit_conn指令则用于在特定的location或server块中启用连接限制。

1.3.令牌桶算法(ngx_http_limit_req_module)

令牌桶算法是一种更为复杂的限流算法。它通过固定速率向桶中添加令牌。每个请求都需要消耗一个令牌才能被处理。如果桶中有足够的令牌,请求将立即被处理;如果没有令牌,则请求可以被延迟处理或拒绝。这种算法允许一定程度的突发流量,因为桶中可以积累令牌以应对短时间内的请求峰值。

虽然ngx_http_limit_req_module模块本身并不直接实现令牌桶算法,但可以通过结合limit_req_zone、limit_req以及burst和nodelay参数来模拟令牌桶算法的行为。burst参数定义了当请求超过速率限制时,允许的最大请求数(即桶的容量),而nodelay参数则决定了是否立即处理超过速率的请求。

2.限流实现

Nginx的限流功能主要通过limit_req和limit_conn模块实现。

如果要使用Nginx限流,则需要做到以下两步:

(1)首先,要启用请求限速模块,确保nginx已经编译并启用了limit_req和limit_conn模块,nginx默认是开启的,因此确认编译的时候没有通过--without-http_limit_req_module和--without-http_limit_conn_module关闭这两个模块。

(2)然后,在nginx的配置文件中设置请求限速规则,通过使用limit_req_zone指令来定义请求限速的共享内存区域。该指令指定了限速的区域名称、存储限速状态的内存大小以及限速的参数。

3.限流配置

包含两种不同的模块配置。

3.1.limit_req限流配置

limit_req模块用于限制每秒的请求次数。该模块基于令牌桶(Token Bucket)算法,每个请求在处理前必须从令牌桶中获取一个令牌,如果没有令牌可用,则请求被延迟或拒绝。

limit_req模块通过定义共享内存区域来存储限流信息,并在特定的上下文中应用限流策略。

3.1.1.定义共享内存区域

首先,需要定义一个共享内存区域来存储请求的计数信息。可以使用limit_req_zone指令来完成。语法如下:

limit_req_zone $variable zone={name}:{size} rate={rate};

例如

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

这里,$binary_remote_addr表示的客户端IP地址。

zone=one:10m表示定义名为one的共享内存区域,大小为10MB。

rate=1r/s表示限制每秒最多1个请求。

3.1.2.应用限流策略

在定义共享内存区域后,可以在server或location上下文中使用limit_req指令来应用限流策略。

配置格式如下

limit_req zone={name} [burst={number}] [nodelay];

其中,zone={name}指定使用名的共享内存区域。

burst={number}指定允许突发请求的个数。

nodelay表示立即处理突发请求,不进行延迟。

3.1.3.示例配置详解

以下是一个完整的示例配置:

http {
    # 定义共享内存区域
    limit_req_zone $binary_remote_addr zone=one:20m rate=3r/s;
    server {
        listen 7788;
        server_name abc.com;
        location / {
            # 应用限流策略
            limit_req zone=one burst=10 nodelay;
            # 代理到后端服务器
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

这个示例中,Nginx会限制每个客户端每秒最多发送3个请求,并允许最多10个突发请求。

3.2.limit_conn限流配置

limit_conn模块用于限制同时连接数。该模块控制每个特定键(如IP地址或用户)允许的最大并发连接数。

3.2.1.定义共享内存区域

这里也需要定义一个共享内存区域来存储连接计数信息。可以使用limit_conn_zone指令来完成。语法如下:

limit_conn_zone $variable zone={name}:{size};

$binary_remote_addr表示的客户端IP地址。

zone={name}:{size}定义共享内存区域的名称,并指定内存大小。

3.2.2.应用限流策略

在定义共享内存区域后,可以在server或location上下文中使用limit_conn指令来应用限流策略。语法如下:

limit_conn {zone_name} {number};

{zone_name}指定使用的共享内存区域名称。

{number}表示允许的最大并发连接数。

3.2.3.示例配置详解

以下是一个完整的示例配置:

http {
    # 定义共享内存区域
    limit_conn_zone $binary_remote_addr zone=addr:20m;
    server {
        listen 80;
        server_name example.com;
        location / {
            # 应用限流策略
            limit_conn addr 20;
            # 代理到后端服务器
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

示例中,Nginx会限制每个客户端最多允许20个并发连接。