preaccess阶段

166 阅读3分钟

preaccess阶段有两个模块,一个是限制每秒连接的请求数limit_req模块,一个是限制并发的连接数limit_conn模块。

一、limit_conn模块

limit_conn模块用来限制请求并发数的,它默认是被编译进nginx,可以使用--without-http_limit_conn_module进行禁用。

limit_conn模块的相关配置是针对所有的worker进程的,并不是某一个worker进程,因为它使用了共享内存。

1、指令

  • limit_conn_zone:定义共享内存的大小,以及key关键字。limit_conn_zone key zone=name:size。nginx中凡是使用zone的地方都使用的是共享内存,因为zone是来定义共享内存的名称和大小的。该指令只能在http上下文中使用。

  • limit_conn:限制并发连接数。limit_conn:  zone number。该指令可以放在http、server、location上下文中。number最小为1。

  • **limit_conn_log_level:**限制发生时的日志级别。默认是error,可选值有:info、notice、warn、error。

  • limit_conn_status:修改返回给客户端的状态码。如:limit_conn_status 503。改指令可以在http、server、location上下文中使用。

2、案例

    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        ......
        error_log logs/error.log info;
        
       location / {
           limit_conn_status 500;
           limit_conn_log_level warn;
           limit_rate 20;
           limit_conn addr 1;
       }
        ......
    }

解析:

  • binary_remote_addr:该变量的值为XForward_For的值,同binary\_remote\_addr:该变量的值为X-Forward\_For的值,同remote_addr一样,只是binart_remote_addr是一个二进制格式的ip地址,长度占用4个字节,一个会话占用32字节,binart\_remote\_addr是一个二进制格式的ip地址,长度占用4个字节,一个会话占用32字节,remote_addr长度占用7~15字节,一个会话占用32或64字节。

  • error_log:后面一定要加info,不然连接日志为warn的不显示。

  • limit_rate:返回速率,这里设置每秒返回20字节。

这几监听的是localhost:8000,在浏览器打开两个页面,同时访问,会发现第二个页面响应为500。

二、limit_req模块

limit_req模块是用来限制一个连接上每秒连接的请求数,它默认是编译进nginx中的,可以使用--without-http_limit_req_module禁用。它使用的生效算法是leak bucket,生效范围是所有的worker进程。

1、leaky bucket算法

思想很简单,就是限流,保证nginx每秒处理的请求数量不变,多出来的流量存储起来。如上图,当盆已经满的时候,再有流量进来,nginx就会返回错误;当盆还没有慢的时候,用户请求会被存储起来,用户的响应很变慢。

2、limit_req指令

  • limit_req_zone:定义共享内存的大小,以及key关键字和速率。limit_req_zone key zone=name:size rate=rate,rate的速率为r/m或者r/s。1r/s表示1s中处理一个请求,2r/s表示1s中处理两个请求。

  • limit_req:限制并发连接数。limit_req zone=name [burst=number] [nodelay],burst(盆)默认为0,nodelay表示对burst中的请求不再做延时处理,而是立即处理。

  • limlit_req_log_level:限制发生时的日志级别,为info、warn、error、notice。

  • limit_red_status:定义返回给用户的状态码。

三、补充

1、limit_req和limit_conn同时配置,哪个生效?

limit_req生效,因为它的处理阶段在limit_conn之前,一旦它返回响应,limit_conn就等不到处理请求。