Nginx:如何设置“limit_conn”和“limit_req”?

Che*_*mer 5 nginx

我在ubuntu 14.04上使用 nginx版本 1.6.2

我试图通过引用nginx 文档来输入limit_connlimit_req配置文件。

Nginx 在没有limit_connlimit_req选项的情况下运行良好

以下是带有日志消息的 nginx 配置测试用例。

我不知道我的代码有什么问题。


案例 1 - 完整配置

/etc/nginx/nginx.conf

http {
    ...
    include /etc/nginx/sites-enabled/*;
    ...
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
    ...
}
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/sites-enabled/service.conf

server {
    ...
    location / {
        limit_conn conn_limit_per_ip 30;
        limit_req zone=req_limit_per_ip burst=5 nodelay;
        ...
    }        
    ...
}
Run Code Online (Sandbox Code Playgroud)

log message

unknown limit_req_zone "req_limit_per_ip" in /etc/nginx/sites-enabled/service.conf
Run Code Online (Sandbox Code Playgroud)

案例 2 -limit_req从启用站点的配置文件中删除

/etc/nginx/nginx.conf

http {
    ...
    include /etc/nginx/sites-enabled/*;
    ...
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
    ...
}
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/sites-enabled/service.conf

server {
    ...
    location / {
        limit_conn conn_limit_per_ip 30;
        ...
    }        
    ...
}
Run Code Online (Sandbox Code Playgroud)

log message

the size 10485760 of shared memory zone "conn_limit_per_ip" conflicts with already declared size 0 in /etc/nginx/nginx.conf
Run Code Online (Sandbox Code Playgroud)

案例 3 -limit_conn从启用站点的配置文件中删除

/etc/nginx/nginx.conf

http {
    ...
    include /etc/nginx/sites-enabled/*;
    ...
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
    ...
}
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/sites-enabled/service.conf

server {
    ...
    location / {
        limit_req zone=req_limit_per_ip burst=5 nodelay;
        ...
    }        
    ...
}
Run Code Online (Sandbox Code Playgroud)

log message

unknown limit_req_zone "req_limit_per_ip" in /etc/nginx/sites-enabled/service.conf
Run Code Online (Sandbox Code Playgroud)

案例 4 - 从启用站点的配置文件中删除所有内容

/etc/nginx/nginx.conf

http {
    ...
    include /etc/nginx/sites-enabled/*;
    ...
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
    ...
}
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/sites-enabled/service.conf

server {
    ...
    location / {
        ...
    }        
    ...
}
Run Code Online (Sandbox Code Playgroud)

log message

[OK] - nginx reloaded well
Run Code Online (Sandbox Code Playgroud)

案例 5 - 删除limit_req_zonelimit_req

/etc/nginx/nginx.conf

http {
    ...
    include /etc/nginx/sites-enabled/*;
    ...
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
    ...
}
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/sites-enabled/service.conf

server {
    ...
    location / {
        limit_conn conn_limit_per_ip 30;
        ...
    }        
    ...
}
Run Code Online (Sandbox Code Playgroud)

log message

the size 10485760 of shared memory zone "conn_limit_per_ip" conflicts with already declared size 0 in /etc/nginx/nginx.conf
Run Code Online (Sandbox Code Playgroud)

案例 6 - 删除limit_conn_zonelimit_conn

/etc/nginx/nginx.conf

http {
    ...
    include /etc/nginx/sites-enabled/*;
    ...
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
    ...
}
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/sites-enabled/service.conf

server {
    ...
    location / {
        limit_req zone=req_limit_per_ip burst=5 nodelay;
        ...
    }        
    ...
}
Run Code Online (Sandbox Code Playgroud)

log message

unknown limit_req_zone "req_limit_per_ip" in /etc/nginx/sites-enabled/service.conf
Run Code Online (Sandbox Code Playgroud)

Che*_*mer 5

解决方案

合并/etc/nginx/sites-enabled/service.conf/etc/nginx/nginx.conf. 换句话说,删除service.conf文件并servernginx.conf文件的http块上粘贴块。这是代码。

/etc/nginx/nginx.conf

http {

    ..

    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=2r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;

    ..

    server {

        ..

        location / {
            limit_req zone=req_limit_per_ip burst=5 nodelay;
            limit_conn conn_limit_per_ip 30;
        }

        ..
    }
}
Run Code Online (Sandbox Code Playgroud)

变量和测试的含义

  1. limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=2r/s + limit_req zone=req_limit_per_ip burst=5 nodelay

    • 将共享内存设置为 10MB
    • 限制每个 IP 的请求如下
    • rate * burstburst秒为单位设置最大请求数
    • 例如,在这种情况下,最大值是 5 秒内 10(=2*5) 个请求
    • 使用nodelay选项:Nginx 将返回 503 响应并且不处理过多的请求
    • 没有nodelay选项:Nginx 会等待(没有 503 响应)并处理过多的请求,但会有一些延迟
  2. limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m + limit_conn conn_limit_per_ip 30

    • 将共享内存设置为 10MB
    • 在这种情况下,将每个 IP 的连接数限制为 30
    • 请注意,普通浏览器创建 2~8 个连接,SPDY 协议拆分每个连接
    • 如果连接超过此值,Nginx 将返回 503 响应

  • 您对“burst”和“nodelay”指令的理解不正确。如果您将速率设置为 10r/s,Nginx 将返回 503 来请求间隔小于 100 毫秒的请求。`burst` 指令定义了排队的最大请求数,因此如果我在 1 秒内发出 30 个请求,最后 20 个将进入突发队列,一旦突发队列已满,Nginx 将返回 503。 `nodelay` 转发所有请求立即处理,直到突发队列已满,而不是按照设定的速率限制一次处理一个。在您的示例中,Nginx 将同时接受 5 个请求(现在突发已满),然后随着突发队列清除,每 500 毫秒接受 1 个请求 (2认同)