运维知识库-BigHead
  • 首页
  • 电子书-知识库老版本
  • VIP视频免费看
  • 联系作者
  • 随笔
https://github.com/yongxiaodong
  1. 首页
  2. Nginx
  3. 正文

Nginx limit_req_zone限流

2020年07月30日 912点热度 0人点赞 0条评论

首先献上一个本人在生产环境应用的一个较完整的Nginx主配置文件

#
user              www www;
worker_processes  auto;

#Specifies the value for maximum file descriptors that can be opened by this process.
pcre_jit                on; 
worker_rlimit_nofile    66600;
worker_shutdown_timeout 60s;
worker_cpu_affinity     auto;

events {
    use                 epoll;
    worker_connections  66600;
    }

http {
    error_log         /var/log/nginx/error.log;
    access_log        /var/log/nginx/access.log;
    charset       utf-8;
    include       mime.types;
    default_type  application/octet-stream;

    #  老代码需要这个 clientRealIp 头,如果没有,网站会挂
    map http_x_forwarded_forclientRealIp {
        ""                              remote_addr;
        ~^(?P<firstAddr>[0-9\.]+),?.*  firstAddr;
    }

    log_format main        'remote_addr - [remote_addr] -remote_user [time_local]'
        ' "request" statusbody_bytes_sent "http_referer" "http_user_agent" request_length'
        'request_time [http_appid]upstream_addr "upstream_response_length"'
        'upstream_response_time "upstream_status" "upstream_status" host [http_appkey] "request_id"' ;
    log_format json '{"access_time": "time_iso8601", "remote_addr": "remote_addr", "x-forward-for": "http_x_forwarded_for", "method": "request_method", "request_url_path": "uri", "request_url": "request_uri", "status":status, "request_time": request_time, "body_bytes_sent": "body_bytes_sent", "request_length": "request_length", "upstream_host": "upstream_http_host", "upstream_response_length": "upstream_response_length", "upstream_response_time": "upstream_response_time", "upstream_status": "upstream_status", "http_referer": "http_referer", "remote_user": "remote_user", "http_user_agent": "http_user_agent", "request_id": "request_id", "appkey": "http_appkey", "upstream_addr": "upstream_addr"}';

    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;

    proxy_next_upstream error http_502 timeout;
    proxy_next_upstream_tries 2;

    open_file_cache           max=10240 inactive=20s;
    open_file_cache_valid     30s;
    open_file_cache_min_uses  1;
    reset_timedout_connection on;

    keepalive_timeout       45s;
    keepalive_requests      2000;
    client_header_timeout   15s;
    client_body_timeout     15s;
    proxy_connect_timeout   5s;
    variables_hash_max_size 1024;

    server_tokens                 off;
    proxy_intercept_errors        on;
    fastcgi_intercept_errors      on;
    client_header_buffer_size     16k;
    large_client_header_buffers   4 32k;
    client_max_body_size          160m;
    server_names_hash_max_size    512;
    server_names_hash_bucket_size 128;

    gzip on;
    gzip_min_length  1k;
    gzip_buffers  16 8k;
    gzip_comp_level 6;
    gzip_types  text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json application/javascript;
    gzip_vary on;
    gzip_proxied any;

    proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传递请求,而不缓冲到磁盘
    client_body_buffer_size    256k;
    proxy_buffer_size          64k;          #设置代理服务器(nginx)保存用户头信息的缓冲区大小
    proxy_buffers              4 64k;            #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
    proxy_buffering            on;
    limit_req_status  429;
    limit_req_zonehttp_host           zone=open_api_domain:50m rate=2800r/s;
    limit_req_zone arg_appkey          zone=open_api_appkey:50m rate=300r/s;
    limit_req_zonebinary_remote_addr  zone=zone_web_tmp:50m    rate=5r/s;
    limit_req_zone binary_remote_addr  zone=zone_web:50m        rate=30r/s;
    limit_req_zonebinary_remote_addr  zone=zone_web_yjtg:50m   rate=30r/s;
    limit_req_zone binary_remote_addr  zone=zone_open_api:50m   rate=300r/s;

    mapsent_http_cdn_time expires {
        default             -1;
        ~^\d+               sent_http_cdn_time;
    }

    more_clear_headers Pragma;
    set_real_ip_from   0.0.0.0/0;
    real_ip_header     X-Forwarded-For;
    real_ip_recursive  on;
    expiresexpires;
    more_set_headers   "Upstream-Name: proxy_host";

    lua_package_path "{prefix}conf/conf.d/lrc4/?.lua;/opt/nginx/lua_modules/?.lua;/opt/nginx/lua/?.lua;/opt/nginx/lua_modules/?.lua;/opt/nginx/lua/?.lua;;";
    lua_shared_dict  domain_mem          10m;
    lua_shared_dict  open_url_mem_min    10m;
    lua_shared_dict  open_appkey_mem_day 10m;
    lua_shared_dict  my_limit_req_store  30m;
    lua_shared_dict  my_limit_req_api    30m;
    lua_shared_dict  cms_domain_mem      10m;
    lua_shared_dict  cms_domain_vipstatus_mem      20m;

    lua_socket_log_errors off;  # TCP发送失败的时候,会发送error日志到error.log,此过程会有性能开销,建议关闭,避免健康检查中多台机器down了,导致日志一直写入error.log。对于异常的情况请使用ngx.log来记录

    lua_shared_dict healthcheck 2m;  # 存放upstream servers的共享内存,upstream组越多,配置就越大。

    proxy_redirect     off ;
    proxy_http_version 1.1;
    proxy_set_header   Connection  "";
    proxy_set_header   Host host;
    proxy_set_header   X-Forwarded-Forproxy_add_x_forwarded_for;
    proxy_set_header   X-Request-Id request_id;

    resolver 100.100.2.138  100.100.2.136 valid=30s;

    # 静态化varnish缓存,轮训负载均衡主备
    split_clients "request_uri" proxy_cache {
                   50%           master_cache_servers;
                   *             backup_cache_servers;
    }

    server {
        listen 80;
        server_name  ~^\d+\.\d+\.\d+\.\d+;
        setcms_uri '';
        set $mysql_host_uri '';
        return 444;
    }

    ssl_certificate   conf.d/dtkcert/dataoke.com.pem;
    ssl_certificate_key  conf.d/dtkcert/dataoke.com.key;

    include upstream.conf;
    include conf.d/*.conf;
    include testconfig/*.conf;
    include blocksip.conf;
 }




优势:

Nginx限流可以针对客户端的IP进行请求速率限制,既能够强行保证请求的实时处理速度,又能防止恶意攻击或突发流量导致系统被压垮,提升系统的健壮性。

在http模块中新增配置limit_req_zone全局配置

在http模块中新增配置limit_req_zone,如下:

http {
    include       mime.types;
    default_type  application/octet-stream;
    server_tokens off;
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
  • $binary_remote_addr表示根据remote_addr变量的值进行限制
  • zone=mylimit:10m 表示一个大小为10M,名字为myRateLimit的内存区域,根据官方描述,1M的内存大约可以存储16000个IP地址,10M则可以存储约16万IP地址,可以根据实际情况调整
  • rater=2r/s 表示限制每秒2个请求,Nginx 实际上以毫秒为粒度来跟踪请求信息,因此 2r/s 实际上是限制:每500毫秒处理一个请求。这意味着,自上一个请求处理完后,若后续500毫秒内又有请求到达,将拒绝处理该请求,默认返回503错误码,该错误码可以自定义。

在server中调用limit_req_zone

例:

    server {
        listen       8089;
        server_name  localhost;
        root html/shigongbao;
        autoindex on;
        limit_req zone=mylimit burst=4 nodelay;
        location / {
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
 }
  • zone=mylimit 表示调用http全局模块中定义的limit_req_zone zone名
  • burst=4 表示缓冲区突然流量处理,在超过设定的处理速率后能额外处理的请求数。当 rate=2r/s 时,将1s拆成2份,即每500ms可处理1个请求。 当同时有10个请求到达时,rate=2 立刻转发了2个请求到后端服务器,burst=4 缓存或立刻转发了4个请求(是否立刻转发主要看nodelay参数),丢弃了4个请求
  • Nodelay 针对的是burst参数,burst=4 nodelay 表示这4个请求立马处理,不能延迟,相当于特事特办。不过,即使这4个突发请求立马处理结束,后续来了请求也不会立马处理。burst=4 相当于缓存队列中占了4个坑,即使请求被处理了,这4个位置这只能按 500ms一个来释放。

执行ab压力测试

上述配置中rate=2r/s,burst=4,推理出第1秒可以一次性处理5个请求(因为rate=2 500毫秒内的第二个请求会被丢弃)

一次性发送5个请求测试结果,Failed requests: 0

[root@cs2 Yearning-go]# ab -n 5 -c 5 http://192.168.1.30:8089/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.30 (be patient).....done


Server Software:        nginx
Server Hostname:        192.168.1.30
Server Port:            8089

Document Path:          /
Document Length:        394 bytes

Concurrency Level:      5
Time taken for tests:   0.002 seconds
Complete requests:      5
Failed requests:        0
Write errors:           0
Total transferred:      2545 bytes
HTML transferred:       1970 bytes
Requests per second:    2019.39 [#/sec] (mean)
Time per request:       2.476 [ms] (mean)
Time per request:       0.495 [ms] (mean, across all concurrent requests)
Transfer rate:          1003.78 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       1
Processing:     1    1   0.1      1       1
Waiting:        1    1   0.1      1       1
Total:          1    1   0.1      1       1

Percentage of the requests served within a certain time (ms)
  50%      1
  66%      1
  75%      1
  80%      1
  90%      1
  95%      1
  98%      1
  99%      1
 100%      1 (longest request)

一次性发送6个请求测试结果,有一个请求被丢弃,Failed requests: 1

[root@cs2 Yearning-go]# ab -n 6 -c 6 http://192.168.1.30:8089/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.30 (be patient).....done


Server Software:        nginx
Server Hostname:        192.168.1.30
Server Port:            8089

Document Path:          /
Document Length:        394 bytes

Concurrency Level:      6
Time taken for tests:   0.018 seconds
Complete requests:      6
Failed requests:        1
   (Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Write errors:           0
Non-2xx responses:      1
Total transferred:      3226 bytes
HTML transferred:       2464 bytes
Requests per second:    328.62 [#/sec] (mean)
Time per request:       18.258 [ms] (mean)
Time per request:       3.043 [ms] (mean, across all concurrent requests)
Transfer rate:          172.55 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        4    5   0.3      5       5
Processing:     5    5   0.0      5       5
Waiting:        5    5   0.1      5       5
Total:          9    9   0.3     10      10
ERROR: The median and mean for the total time are more than twice the standard
       deviation apart. These results are NOT reliable.

Percentage of the requests served within a certain time (ms)
  50%     10
  66%     10
  75%     10
  80%     10
  90%     10
  95%     10
  98%     10
  99%     10
 100%     10 (longest request)

Nginx error日志记录被丢弃的包如下:

2020/07/29 16:00:08 [error] 4471#0: *895 limiting requests
标签: 暂无
最后更新:2021年03月07日

BigHead

保持饥渴的专注,追求最佳的品质

点赞
下一篇 >

文章评论

取消回复
文章归档
  • 2022年7月
  • 2021年6月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2020年8月
  • 2020年7月
分类目录
  • ELK
  • Jenkins
  • K8S
  • Nginx
  • Openvpn
  • Python
  • 小技能
  • 未分类

COPYRIGHT © 2020 运维知识库-BigHead. ALL RIGHTS RESERVED.

蜀ICP备16012425号