nginx限流配置和说明

1.limit_req_zone

1.1 指令limit_req_zone的使用

# 定义一个以IP为限制请求的方式,名字为req_limit_zone,开辟10M的共享内存区域,每秒处理的速率为10个请求

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

说明 :limit_req_zone指令通常在 HTTP 块中定义,使其可在多个上下文中使用,它需要以下三个参数:

  • key - 定义应用限制的请求特性。示例中使用的是 Nginx 嵌入变量binary_remote_addr(二进制客户端地址)

  • zone - 定义用于存储每个 IP 地址状态以及被限制请求 URL 访问频率的共享内存区域。保存在内存共享区域的信息,意味着可以在 Nginx 的 worker 进程之间共享。定义分为两个部分:通过zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000 个 IP 地址的状态信息,大约需要 1MB,所以示例中区域可以存储 160000 个 IP 地址。

  • rate - 定义最大请求速率。在示例中,速率不能超过每秒 10 个请求。Nginx 实际上以毫秒的粒度来跟踪请求,所以速率限制相当于每 100 毫秒 1 个请求。因为不允许”突发情况”,这意味着在距离前一个请求 100 毫秒内到达的请求将被拒绝。

1.2 指令limit_req的使用

limit_req zone=req_limit_zone burst=10 nodelay;

说明:

  • limit_req zone=req_limit_zone; 每个 IP 地址被限制为每秒只能请求 10 次 URL,更准确地说,在距离前一个请求的 100 毫秒内不能请求该 URL。
  • limit_req zone=req_limit_zone burst=10; burst 参数定义了超出 req_limit_zone指定速率的情况下(示例中的 req_limit_zone区域,速率限制在每秒 10 个请求,或每 100 毫秒一个请求),客户端还能发起多少请求。距离上一个请求 100 毫秒内到达的请求将会被放入队列,我们将队列大小设置为 10。

这意味着,如果从一个给定 IP 地址发送 11 个请求,Nginx 会立即将第一个请求发送到上游服务器群,然后将余下 10 个请求放在队列中。然后每 100 毫秒转发一个排队的请求,只有当传入请求使队列中排队的请求数超过 10 时,Nginx 才会向客户端返回 503。

配置 burst 参数将会使通讯更流畅,但是可能会不太实用,因为该配置会使站点看起来很慢。在上面的示例中,队列中的第 10 个包需要等待 1 秒才能被转发,此时返回给客户端的响应可能不再有用。

  • limit_req zone=req_limit_zone burst=10 nodelay;  使用 nodelay 参数,可以实现无延迟的排队;Nginx 仍将根据 burst 参数分配队列中的位置,当一个请求到达时,只要在队列中能分配位置,Nginx 将立即转发这个请求。将队列中的该位置标记为”taken”(占据),并且不会被释放以供另一个请求使用,直到一段时间后才会被释放(在这个示例中是,100 毫秒后)。

假设如前所述,队列中有 10 个空位,从给定的 IP 地址发出的 11 个请求同时到达。Nginx会立即转发这个 11 个请求,并且标记队列中占据的 10 个位置,然后每 100 毫秒释放一个位置。如果是15个请求同时到达,Nginx 将会立即转发其中的 11 个请求,标记队列中占据的 10 个位置,并且返回 503 状态码来拒绝剩下的 4 个请求。

2.limit_conn_zone

2.1 指令limit_conn_zone的使用

# 定义一个以IP为限制连接的方式,名字为conn_limit_zone,并开辟10m的共享内存区

limit_conn_zone $binary_remote_addr zone=conn_limit_zone:10m;

2.2 指令limit_conn的使用

limit_conn conn_limit_zone 2;

说明:

# 使用定义conn_limit_zone的连接限流,限制每个IP地址只允许同时创建2个连接

3.黑白名单

3.1 allow(白名单)、deny(黑名单) 方式

     参考:

location / {
    deny  192.168.1.1;     #支持单个IP
    allow 192.168.1.0/24;  #支持一个网段
    allow 2001:0db8::/32;  #支持ipv6
    deny all;   #支持all匹配到所有
}

假如192.168.1.1 匹配到了上面的第1,2,4行,因为deny和allow是顺序匹配,匹配到即停止。所以第一条匹配到后,就直接deny了

3.2 ngx_http_geo_module 限流

参考:

geo $limit {
    default         1;
    10.0.0.0/8         0;
    192.168.1.0/24     0;
}
map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=geo_req_zone:10m rate=10r/s;
server {
    location /limit_demo {
        limit_req zone=geo_req_zone burst=10 nodelay;

        # ...
    }
}

这个例子同时使用了 geo 和 map 指令。geo 块将给在白名单中的 IP 地址对应的 $limit 变量分配一个值 0,给其它不在白名单中的分配一个值 1。然后我们使用一个映射将这些值转为 key,如下:

  • 如果变量的值是0,limit_key变量将被赋值为空字符串
  • 如果变量的值是1,limit_key变量将被赋值为客户端二进制形式的 IP 地址

两个指令配合使用,白名单内 IP 地址的$limit_key变量被赋值为空字符串,不在白名单内的被赋值为客户端的 IP 地址。当limit_req_zone后的第一个参数是空字符串时,不会应用“流量限制”,所以白名单内的 IP 地址(10.0.0.0/8 和192.168.1.0/24 网段内)不会被限制。其它所有 IP 地址都会被限制到每秒 10 个请求(每100毫秒1个请求)。

4. 发送到客户端的错误代码

可以使用limit_req_status指令来设置为其它状态码,默认503

5. 限流条件的扩展

除了上面用到的$binary_remote_addr ,其它常用的限流条件还包括:

 $binary_remote_addr    二进制的客户端地址,对于Ipv4,值的长度使用为4个字节,对于ipv6地址,值的长度始终为16个字节

 $server_name  接受请求的服务器的名称

 $cookie_name    cookie名

 $http_name  任意请求头字段,变量名的最后一部分是转换成小写的字段名,其中的破折号替换为下划线

 $realpath_root  与当前请求 的根或别名指令的值 相对应的绝对路径名 ,所有符号链接都解析为真实路径

 $remote_addr  客户地址

 $remote_user  随基本身份验证提供的用户名

 $request_uri  完整的原始请求 URI(带参数)

 $scheme  请求方案,“ http”或“ https”

 $uri 请求中的当前 URI

6. 完整的配置文件(nginx.conf):

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;
    #限流配置开始************************************************************
    #限流设置
    limit_req_zone $binary_remote_addr zone=req_limit_zone:10m rate=10r/s;
    
    #根据IP地址来限制,存储内存大小10M
    limit_conn_zone $binary_remote_addr zone=conn_limit_zone:10m;
    #geo限流
    geo $limit {
        default         1;
        10.0.0.0/8         0;
        192.168.1.0/32     0;
    }
    map $limit $limit_key {
        0 "";
        1 $binary_remote_addr;
    }    
    limit_req_zone $limit_key zone=geo_req_zone:10m rate=10r/s;
    #限流配置结束************************************************************

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }
  
        # 限流配置demo 
        location /limit_demo {
            #allow配置白名单,支持一个网段或者单个地址
            allow 192.168.1.0/24;
            #deny配置黑名单,支持一个网段或者单个地址
            deny 192.168.2.0/24;
            #流量限制
            limit_req zone=req_limit_zone burst=10 nodelay;
            # 连接数限制 
            limit_conn conn_limit_zone 2;
            # geo(白名单)流量限制(粒度更细一些)
            limit_req zone=geo_req_zone burst=10 nodelay;
            # 返回客户端错误代码
            limit_req_status 503;

            proxy_pass http://192.168.0.1:18081;
        }


        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值