nginx 限速之limit_conn

本文介绍了如何使用Nginx的limit_req,limit_conn和limit_rate模块来限制请求量、连接数和响应速度,重点讲解了limit_conn_module及其limit_conn_zone指令,包括设置zone、limit_conn和日志级别,以及dry_run模式的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在工作中经常会遇到用户大量请求某个接口和一些大流量的恶意攻击,可以通过nginx对同一个ip的连接数,请求,进行限制.

        通过nginx我们有三种限速方式分别是: 限制请求数(request),限制连接数(connection),限制响应速度(rate),分别对应nginx的limit_req,limit_conn和limit_rate三个模块,limit_conn和limit_req模块类似,有许多指令组成一个大的模块,两个模块之间很多指令的命名方式和用法大同小异.

        ngx_http_limit_conn_module 模块主要是用于根据特定的key来限制连接的数量,如根据ip地址来限制连接数.需注意的是并不是所有的连接都会被算入其中,只有当一个连接的整个请求头被读取并且已经被nginx服务器处理的时候才会被算入限制中.

1. ngx_http_limit_conn_module模块

1. limit_conn_zone 指令

#语法配置
Syntax: limit_conn_zone key zone=name:size;
Defaule: -
Context: http  #作用域

limit_conn_zone $binary_remote_addr zone=${name}:10m #示例

说明:

 limit_conn_zone:  只能够在http块用使用

 key: 可以设置为$variable使用Nginx内置变量作为键(一般经常使用客户端ip地址作为键:$remote_addr变量的长度为7字节到15字节,而存储状态在32位平台中占用32字节或64字节,在64位平台中占用64字节。)$binary_remote_addr变量的长度是固定的4字节,存储状态在32位平台中占用32字节或64字节,在64位平台中占用64字节。1M共享空间可以保存3.2万个32位的状态,1.6万个64位的状态)。zone=name定义区域名称(名称随意起,在limit_conn配置项中调用时对应就好),size定义各个键共享内存空间大小。如果共享内存空间被耗尽,服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误。

name: 就是这个zone的命名,name需要全局唯一,limit_conn 命令根据name来查找对应zone进行相应限制规则的匹配.

size:  定义这个zone的大小,也就是nginx会在内存中开辟多大的空间来存储这个zone的相应信息,主要和前面定义的key的大小有关系,需要注意的是当内存带下耗尽的时候,nginx会直接返回错误码limit_conn_status给后续的请求(If the zone storage is exhausted, the server will return the error to all further requests.)

2. limit_conn指令

Syntax:  limit_conn zone number;  #语法
Default:
Context: http,server,location  #作用域

说明:

limit_conn: 使用由limit_conn_zone定义的拦截规则,并设置具体的限制连接数量,当超过这个数字时返回503(server)的错误.定义的存储区域key对应的总的网络连接数进行限流。可以按照IP来限制IP维度的总连接数,或者按照服务域名来限制某个域名的总的连接数(只有那些被nginx处理的且已经读取了整个请求头的请求连接才会被计数器统计,在http,server,location三个块中使用,但是要搭配limit_conn_zone使用

zone: 是在limit_conn_zone中的name变量,对应这全局唯一的zone,负责确定限制连接数的依据

number: 限制的连接数,zone和number组合就可以完成连接数的限定功能,注意number必须是数字而不能使用变量.

示例:

 limit_conn_zone $binary_remote_addr zone=addr:10m;
 ​
 server {
     location /download/ {
         limit_conn addr 1;
     }

3. limit_conn_log_level指令

Syntax:	limit_conn_log_level  info|notice|warn|error  #语法
Default:    limit_conn_log_level error;   #默认
Context:	http, server, location  #作用域

功能: 当达到最大限制规则的连接数后,记录日志的等级。会输出到error.log中而不是access.log,调成info的话会有较多的日志输出,需要额外注意硬盘容量等相关问题。

4.limit_conn_status指令

Syntax:	limit_conn_status code
Context:	http, server, location
Default:	limit_conn_status 503

功能:当超过限制规则后,返回的响应状态码,默认是503,如果是一些有特殊需求的场景,可以手动调整为403之类的状态码,需要注意的是并不是所有的状态码都可以使用,nginx官方限定状态码必须在400到599之间。

5.limit_conn_dry_run指令

 Syntax: limit_conn_dry_run on | off;
 Default:    limit_conn_dry_run off;
 Context:    http, server, location
 This directive appeared in version 1.17.6.

功能: dry_run模式的意义在于试运行而不对线上业务造成影响。设置为on之后,前面的limit_conn指令并不会真正生效,但是limit_conn_zone指令会生效,nginx会在内存中存储计算相关的数据.

<think>好的,我现在要处理用户关于Nginx配置的问题,具体是关于`limit_conn_zone`和`limit_conn`指令的使用。用户给出了一个配置示例,并希望了解其含义和工作原理。我需要先理解用户的问题,然后逐步解释清楚。 首先,用户提供的配置片段中有`limit_conn_zone $variable zone=name:size;`,接着在server块里使用了`limit_conn one 1;`和`limit_rate 300k;`。我需要确认用户是否正确理解了这些指令的作用,以及配置是否存在潜在问题。 接下来,我需要回忆Nginx限速模块相关知识。`limit_conn_zone`用于定义共享内存区域,存储连接数信息。`$variable`通常是客户端的标识,如`$binary_remote_addr`(二进制格式的客户端IP)。用户示例中的`$variable`可能需要替换成正确的变量。用户示例中的zone命名为`name`,但后面的server块中却用了`one`,这明显不一致,这是一个错误,需要指出。 然后,`limit_conn one 1;`中的`one`应该对应`limit_conn_zone`中定义的zone名称,但用户示例中zone的名称是`name`,这里应该是`name`,所以这里存在命名不匹配的问题,会导致配置不生效或出错。需要提醒用户注意这一点。 另外,`limit_conn`指令的参数是否正确?`limit_conn zone number;`,这里的number是每个客户端允许的最大并发连接数。用户设置为1,是正确的,但需要确认是否理解其含义。 还有`limit_rate 300k;`,这是限制每个连接的传输速率为300KB/s。需要说明这是针对每个连接的速度限制,而不是总速度。如果有多个连接,总速度会叠加。这点可能需要进一步解释。 用户可能存在的误区包括:变量使用错误(如未使用正确的客户端标识符)、zone名称不一致、对连接限制和速率限制的区别不清晰。需要逐一指出这些点,并给出正确的配置示例。 此外,还需要提到配置中的注意事项,比如共享内存大小`size`的设置是否足够,以及`limit_conn_zone`应该放在http块中,而不是server块里。用户示例中的配置是否放在正确的位置? 最后,总结配置的作用,解释清楚每个指令的功能,并确保用户理解如何正确应用这些配置来限制并发连接和速率。</think>### 一、配置解析 您提供的 Nginx 配置实现了 **并发连接数限制** 和 **传输速率限制**,但存在关键错误需要修正。完整修正后的配置如下: ```nginx http { # 定义共享内存区(必须放在 http 块内) limit_conn_zone $binary_remote_addr zone=conn_zone:10m; # 修正点1 server { listen 80; server_name www.abc.com; location / { limit_conn conn_zone 1; # 修正点2:zone名称需一致 limit_rate 300k; # 单个连接限速300KB/s proxy_pass http://backend; } } } ``` --- ### 二、核心指令详解 #### 1. `limit_conn_zone`:定义连接限制的存储区 - **语法**: `limit_conn_zone $key zone=name:size;` - **参数说明**: - `$key`:标识客户端的变量,常用 `$binary_remote_addr`(客户端IP的二进制形式,内存效率高) - `zone=name:size`:定义共享内存区名称和大小(例如 `10m` 可存储约8万IP的连接状态) #### 2. `limit_conn`:应用连接限制规则 - **语法**: `limit_conn zone_name max_connections_per_key;` - **示例**: `limit_conn conn_zone 1;` 表示每个客户端IP最多允许1个并发连接 #### 3. `limit_rate`:限制单个连接传输速率 - **语法**: `limit_rate speed;` - **示例**: `limit_rate 300k;` 限制每个连接的传输速率为300KB/s --- ### 三、原配置错误修正 | 错误点 | 原配置 | 修正后 | 说明 | |-------|--------|--------|------| | 1. 未使用有效客户端标识 | `$variable` | `$binary_remote_addr` | `$variable` 是无效变量,需替换为实际标识 | | 2. zone名称不匹配 | `zone=name` 但使用 `limit_conn one` | 统一为 `conn_zone` | zone名称必须一致 | | 3. 共享内存区位置错误 | 直接写在server块外 | 放入 `http` 块 | `limit_conn_zone` 必须定义在 `http` 上下文 | --- ### 四、工作原理解析 1. **连接数限制流程**: - 客户端发起请求 → Nginx 根据 `$binary_remote_addr` 提取客户端IP - 检查 `conn_zone` 内存区中该IP的当前连接数 - 若连接数 ≥1 → 返回 `503 Service Temporarily Unavailable` 错误 - 若连接数 <1 → 允许建立连接,计数器+1 2. **速率限制效果**: - 每个连接独立限速300KB/s(例如:若客户端通过2个连接下载,总速度可达600KB/s) --- ### 五、高级优化建议 #### 1. 自定义错误响应 默认返回 `503`,可指定友好页面: ```nginx error_page 503 /error/limit.html; location = /error/limit.html { root /usr/share/nginx/html; internal; } ``` #### 2. 组合其他限制策略 - **叠加速率限制**:结合 `limit_req` 模块限制请求频率 ```nginx limit_req_zone $binary_remote_addr zone=req_zone:10m rate=10r/s; limit_req zone=req_zone burst=20; ``` - **IP白名单**:绕过限制的关键IP ```nginx geo $limit { default 1; 192.168.1.0/24 0; # 内网IP不受限 } map $limit $conn_limit { 1 $binary_remote_addr; 0 ""; } limit_conn_zone $conn_limit zone=conn_zone:10m; ``` #### 3. 监控内存区状态 通过 `nginx-module-vts` 等工具监控 `conn_zone` 使用情况,避免内存溢出。 --- ### 六、性能测试方法 1. **使用 `ab` 压测连接数限制**: ```bash ab -n 100 -c 10 http://www.abc.com/ # 并发10请求,观察503错误率 ``` 2. **验证速率限制**: ```bash curl -o /dev/null http://www.abc.com/largefile.zip # 观察下载速度是否≤300KB/s ``` --- ### 七、注意事项 1. **共享内存大小估算**: 每个IP约占用128字节,`10m` 内存可存储约 `10*1024*1024 / 128 ≈ 81920` 个IP。 2. **连接释放机制**: Nginx 在连接关闭后立即减少计数器,但若客户端异常断连,需等待 `keepalive_timeout` 超时后释放。 3. **与速率限制的差异**: | 限制类型 | 指令 | 控制维度 | |---------------|----------------|-------------------| | 连接数限制 | `limit_conn` | 并发TCP连接数 | | 请求频率限制 | `limit_req` | 单位时间HTTP请求数 | | 传输速率限制 | `limit_rate` | 单个连接带宽 | --- ### 八、完整配置示例 ```nginx http { limit_conn_zone $binary_remote_addr zone=conn_zone:10m; server { listen 80; server_name www.abc.com; # 自定义503错误页面 error_page 503 /error/limit.html; location = /error/limit.html { internal; root /usr/share/nginx/html; } location / { limit_conn conn_zone 1; # 单IP并发连接≤1 limit_rate 300k; # 单连接限速300KB/s proxy_pass http://backend; } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值