Nginx 使用传入标头 $http_q 进行多重速率限制

Nginx 使用传入标头 $http_q 进行多重速率限制

我在 http 块中有一个如下的速率限制配置:

# Rate limit config declaration
map $http_q $r_b001 {
        b001 "1";
}

# Zone config
limit_req_zone $r_b001 zone=b001:100m rate=20r/s;

# Rate limit config declaration
map $http_q $r_c001 {
        c001 "1";
}

# Zone config
limit_req_zone $r_c001 zone=c001:100m rate=25r/s;

在位置块内我有

location /c001{
        limit_req zone=c001 burst=1 nodelay;
        limit_req_status 429;
        other config...
}

location /b001{
        limit_req zone=b001 burst=1 nodelay;
        limit_req_status 429;
        other config...
}

现在,当我使用 b001 键和 c001 运行负载测试时,我没有获得所需的速率限制控制。如果我添加更多键和相关配置,偏差会更大。我哪里做错了,如何实现这种基于每个位置的每个键的速率限制。

完整配置如下:

geoip2 /etc/nginx/geoip/geoLite-2Country/GeoLite2-Country.mmdb {
        $geoip2_data_country_iso_code country iso_code;
}

include /etc/nginx/conf.d/geoip_config/*.conf;

include /etc/nginx/conf.d/blacklisted_config/*.conf;

##########################################################################################
# Whitelist config declaration
geo $whitelist_b001 {
        default 1;
}

# Rate limit config declaration
map $http_q $r_b001 {
        b001 "1";
    default $request_id;
}

# Zone config
limit_req_zone $r_b001 zone=b001:100m rate=25r/s;

# Rate with White limit config
map $http_q $rw_b001 {
        b001 $whitelist_b001;
        default "0";
}

##########################################################################################
# Whitelist config declaration
geo $whitelist_c001 {
        default 1;
}

# Rate limit config declaration
map $http_q $r_c001 {
        c001 "1";
    default $request_id;
}

# Zone config
limit_req_zone $r_c001 zone=c001:100m rate=15r/s;

# Rate with White limit config
map $http_q $rw_c001 {
        c001 $whitelist_c001;
        default "0";
}


# API Check, regex matches to 1 if one value corresponds to 1
map $r_b001$r_c001 $API_CHECK {
        default 0;
        ~((1)) 1;
}

#Pass through check, regex matches to 1 if one value corresponds to 1
map $rw_b001$rw_c001 $PASS_THROUGH{
        ~((1)) 1;
}

server {
    #*****************************
    # LISTEN PORT AND SERVER NAME
    #*****************************
      
    listen 443 ssl http2; 
    server_name api.com;
       
    client_body_buffer_size 16k;
    client_max_body_size 16k;

    access_log /var/log/nginx/app/access.log json_output;

    #*****************************
    # ROOT PATH
        #*****************************
    root /var/www/html;

        #*****************************
        # INDEX PAGE
        #*****************************
        location / {
                try_files $uri$args $uri$args/ =404;
        }

       #***************************************
       # Key and IP Validators
       #**************************************

       if ($API_CHECK = 0) {
            return 401 '{"status": "failure","status_code": 401 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "API key is Invalid"}';
       }

       if ($allowed_country = no) {
               return 403 '{"status": "failure","status_code": 403 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "Your request to this site is forbidden"}';
       }

       if ($blacklisted_ip = 1) {
        return 403 '{"status": "failure","status_code": 403 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "Your request to this site is forbidden"}';
       }

       if ($PASS_THROUGH = 0) {
            return 403 '{"status": "failure","status_code": 403 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "Your request to this site is forbidden"}';
       }

        #*****************************
    # Application re-route
    #*****************************
    location ^~ /api {
        rewrite ^/api/(.*)$ /proxyapi/$http_q/$1?$args last;
        }

        location ^~ /proxyapi/b001 {
                        # Limit req zone inside its own block
                        limit_req zone=b001 burst=1 nodelay;
                        limit_req_status 429;
                        alias /var/www/html/risk_app/public;
                        try_files $uri $uri/ @risk_laravel_b001;
                        index index.php;

                        # Deny .htaccess
                        location ~ /\.ht{
                                deny all;
                                return 404;
                        }

                        # FastCGI Configuration
                        location ~ \.php$ {
                                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                                fastcgi_pass unix:/run/php/php8.1-fpm.sock;
                                include fastcgi_params;
                                fastcgi_read_timeout 600;
                                fastcgi_param SCRIPT_FILENAME /var/www/html/risk_app/public/index.php;
                                fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
                                fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
                                fastcgi_param NGINX_REQUEST_ID $request_id;
                        }
        }

        location @risk_laravel_b001 {
                    rewrite /proxyapi/b001/(.*)$ /proxyapi/b001/index.php?/$1 last;
            }

    location ^~ /proxyapi/c001 {
                        # Limit req zone inside its own block
                        limit_req zone=default_zone burst=1 nodelay;
                        limit_req_status 429;
                        alias /var/www/html/risk_app/public;
                        try_files $uri $uri/ @risk_laravel_c001;
                        index index.php;

                        # Deny .htaccess
                        location ~ /\.ht{
                                deny all;
                                return 404;
                        }

                        # FastCGI Configuration
                        location ~ \.php$ {
                                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                                fastcgi_pass unix:/run/php/php8.1-fpm.sock;
                                include fastcgi_params;
                                fastcgi_read_timeout 600;
                                fastcgi_param SCRIPT_FILENAME /var/www/html/risk_app/public/index.php;
                                fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
                                fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
                                fastcgi_param NGINX_REQUEST_ID $request_id;
                        }
        }

        location @risk_laravel_c001 {
                    rewrite /proxyapi/c001/(.*)$ /proxyapi/c001/index.php?/$1 last;
            }

        location /ping {
        access_log off;
        return 200 '{"status":"succes","status_code": 200}';
    }

}

相关内容